เราได้เคยพูดถึงการใช้งาน Model ใน CI4 ไปบ้างแล้ว
ในบทความผ่านๆ มา ทั้งการใช้งาน Dynamic Page
และ การสร้างระบบ CRUD เบื้องต้นมาแล้ว สามารถ
ทบทวนได้ที่บทความ
สร้าง Dynamic Page เบื้องต้นใน CodeIgniter 4 http://niik.in/994
https://www.ninenik.com/content.php?arti_id=994 via @ninenik
สร้างระบบ CRUD เพื่อศึกษาฟังก์ชั่นของ Model ใน CodeIgniter 4 http://niik.in/995
https://www.ninenik.com/content.php?arti_id=995 via @ninenik
หากต้องการทำความเข้าใจโดยรวมเกี่ยวกับ Model สามารถอ่านเพิ่มเติมที่หัวข้อนี้
ข้อควรรู้เบื้องต้น เกี่ยวกับ CodeIgniter 4 http://niik.in/991
https://www.ninenik.com/content.php?arti_id=991 via @ninenik
เนื้อหานี้ เราจะมาดูการใช้งานคำสั่งต่างๆ ใน Model เพิ่มเติมอย่างละเอียด พร้อมกับทบทวนเนื้อหาที่เคยแนะนำ
ไปแล้ว เพื่อให้เราสามารถนำความเข้าใจไปปรับประยุกต์ใช้งานได้
เตรียมพร้อมก่อนใช้งาน Model
ให้เราเตรียมรายการเหล่านี้สำหรับใช้ประกอบเนื้อหา
สร้างตาราง users ตามรูปแบบดังนี้
-- -- Table structure for table `users` -- CREATE TABLE `users` ( `id` int(11) NOT NULL, `name` varchar(100) NOT NULL, `email` varchar(100) NOT NULL, `createdate` datetime NOT NULL DEFAULT current_timestamp() ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ALTER TABLE `users` ADD PRIMARY KEY (`id`); ALTER TABLE `users` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; COMMIT;
สร้าง Controller ชื่อ Users.php
app/Controllers/Users.php
<?php namespace App\Controllers; use CodeIgniter\Controller; // เรียกใช้งาน Controller class class Users extends Controller { public function index() { } }
สร้าง Model ชื่อ UsersModel.php
app/Models/UsersModel.php
<?php namespace App\Models; // กำหนด namespace use CodeIgniter\Model; // เรียกใช้งาน Model class class UsersModel extends Model { }
ตอนนี้เราเตรียมทุกอย่างพร้อมแล้ว ไปต่อที่หัวข้อถัดไป
การใช้งาน Models ใน CI4
ใช้จัดการข้อมูลของ app เช่นการเพิ่ม ลบ แก้ไขข้อมูลในฐานข้อมูล และอาจจะมีการกำหนดเงื่อนไข
หรือทิศทางการทำงานของโปรแกรมในลักษณะคล้ายกับ controller บ้างในบางกรณี
ไฟล์เกี่ยวกับ models จะเก็บไว้ที่โฟล์เดอร์ /app/Models
ความสามารถ หรือคุณสมบัติของ Model ใน CI4
- มีการเชื่อมต่อกับ dababase อัตโนมัติ เราไม่ต้องกำหนดการเชื่อมต่อเพิ่มเติม
- รองรับรูปแบบการจัดการแบบ CRUD methods (การอ่าน เพิ่ม ลบ แก้ไขข้อมูล)
- รองรับรูปแบบการตรวจสอบความถูกต้องของข้อมูล หรือ validation
- จะการรูปแบบการแบ่งหน้าข้อมูลอัตโนมัติ
- และอื่นๆ
การเรียกใช้งาน Model
เราสามารถเรียกใช้งาน model ใน Controller ได้ดังนี้
<?php namespace App\Controllers; use CodeIgniter\Controller; // เรียกใช้งาน Controller class class Users extends Controller { public function index() { // เรียกใช้งานแบบ สร้าง instance ใหม่ แบบกำหนดเอง $userModel = new \App\Models\UsersModel(); // เรียกใช้งานแบบ สร้าง instance ใหม่ โดยใช้ฟังก์ชั่น model() $userModel = model('App\Models\UsersModel', false); // เรียกใช้งานแบบ shared instance โดยใช้ฟังก์ชั่น model() $userModel = model('App\Models\UsersModel'); } }
เราสามารถเรียกใช้งาน Model class โดยใช้คำสั่ง use เพื่อให้การเรียกใช้งานกระชับลงได้ดังนี้
<?php namespace App\Controllers; use App\Models\UsersModel; // เรียกใช้งาน Model class use CodeIgniter\Controller; // เรียกใช้งาน Controller class class Users extends Controller { public function index() { // เรียกใช้งานแบบ สร้าง instance ใหม่ แบบกำหนดเอง $userModel = new UsersModel(); // เรียกใช้งานแบบ สร้าง instance ใหม่ โดยใช้ฟังก์ชั่น model() $userModel = model('UsersModel', false); // เรียกใช้งานแบบ shared instance โดยใช้ฟังก์ชั่น model() $userModel = model('UsersModel'); } }
ในที่นี้จะเลือกใช้งาน โดยใช้ฟังก์ชั่น model()
เนื่องจากใน Models ของ CI4 จะทำการเชื่อมต่อกับฐานข้อมูลให้อัตโนมัติ และสามารถเรียกใช้งานผ่านตัวแปร
$this->db ภายใน model class ให้อยู่แล้ว เราไม่ต้องกำหนดการใช้เชื่อมต่อโดยใช้ db_connect() อีก แต่ในบาง
กรณีที่เราต้องการเชื่อมต่อไปยังฐานข้อมูลหรือการตั้งค่่าการเชื่่อมอื่นๆ เพิ่มเติม เราสามารถกำหนด parameter ตัวที่
3 เป็นค่าการเชื่อมที่กำหนดเองได้ ดังนี้
public function index() { // เรียกใช้งานแบบ shared instance ของ model $db = db_connect('custom'); $userModel = model('UsersModel' , true, $db); }
โดย parameter ที่ 1 คือ model class ที่จะใช้งาน
parameter ที่ 2 คือ กำหนดเป็นการสร้าง instance ใหม่หรือไม่ true คือสร้างใหม่ false คือ ใช้ค่าจาก shared ถ้ามี
parameter ที่ 3 คือ การเชื่อมต่อฐานข้อมูล ที่เราสามารถกำหนดเอง เพื่อส่งไปใช้งานใน model
นอกจากการกำหนดการเลือการเชื่อมต่อข้างต้นแล้ว ยังสามารถเลือกกำหนดการเชื่อมใน model class ได้ด้วย จะได้ฮธิบาย
เพิ่มเติมต่อไป
ก่อนที่เราจะลงไปในการตั้งค่าต่างๆ ใน model จะขอเริ่มต้นด้วยรูปแบบการใช้งานแบบเรากำหนดเอง หรือใช้รูปแบบทั่วไป
ในการจัดการภายใน model โดยยังไม่ใช้คำสั่งที่ model มีมาให้ แต่จะใช้ Query Builder จัดการกับข้อมูล
จัดการข้อมูลแบบ CRUD แบบกำหนดเองใน Model
เราจะมาสร้างรูปแบบการจัดการกับฐานข้อมูลแบบกำหนดเอง ภายในไฟล์ model class ซึ่งเป็นรูปแบบการใช้งานทั่วไป ที่เรา
อาจจะต้องได้ใช้บ่อยเป็นปกติ วิธีนี้ เราจะต้องสร้างฟังก์ชั่นต่างๆ เองภายใน model ไม่ว่าจะเป็น แสดงข้อมูล เพิ่ม ลบ และแกไข
ข้อมูล จะได้รูปแบบเป็นดังนี้
App/Models/UsersModel.php
<?php namespace App\Models; // กำหนด namespace use CodeIgniter\Model; // เรียกใช้งาน Model class class UsersModel extends Model // สร้าง Model class โดยสืบทอดจาก Model { protected $_table = 'users'; public function getUsers(){ $builder = $this->db->table($this->_table); $query = $builder->get(); return $query->getResultArray(); } public function view($id){ $builder = $this->db->table($this->_table); $query = $builder->getWhere(['id' => $id]); return $query->getRowArray(); } public function add($data){ $builder = $this->db->table($this->_table); return $builder->insert($data); } public function edit($data, $id){ $builder = $this->db->table($this->_table); return $builder->update($data, ['id' => $id]); } public function del($id){ $builder = $this->db->table($this->_table); return $builder->delete(['id' => $id]); } }
ในการกำหนดค่าตัวแปร และชื่อ method ใน model class จะมีบางชื่อที่เราไม่สามารถกำหนดได้ เพราะถูกใช้เป็นค่า
property ของ model เช่นตัวแปร $table เป็นต้น และคำสั่ง เช่น insert() update() delete() เหล่านี้เป็นต้น ล้วนถูกจองชื่อ
ไว้ หากเรากำหนด จะเกิด error ขึ้น ให้เลี่ยงไปใช้ค่าอื่นแทน
Model แบบกำหนดการทำงานเองข้างตัน รองรับการเพิ่ม ลบ แก้ไข และอ่านค่าข้อมูลในตาราง 'users'
ต่อไปเราจำลองการทำงานโดยกำหนดตัวแปร สำหรับทดสอบการทำงานต่างๆ ใน Controller ไฟล์ ดังนี้
App/Controllers/Users.php
<?php namespace App\Controllers; use App\Models\UsersModel; // เรียกใช้งาน Model class use CodeIgniter\Controller; // เรียกใช้งาน Controller class class Users extends Controller { protected $userModel; public function __construct(){ $this->userModel = model('UsersModel'); } public function index() { $result = $this->userModel->getUsers(); echo "<pre>"; print_r($result); } public function view($id){ $row = $this->userModel->view($id); echo "<pre>"; print_r($row); } public function create(){ $data = [ 'name' => 'test name '.time(), 'email' => 'test email '.time(), ]; if($this->userModel->add($data)){ echo "Created!"; } } public function edit($id){ $data = [ 'name' => 'edit test name '.time(), 'email' => 'edit test email '.time(), ]; if($this->userModel->edit($data, $id)){ echo "Updated!"; } } public function delete($id){ if($this->userModel->del($id)){ echo "Deleted!"; } } }
ในการกำหนด Controller ข้างต้น เราใช้ฟังก์ชั่น __construct() สำหรับกำหนด เรียกใช้งาน model แบบ global ใน
Controller เพื่อที่จะได้ไม่ต้องกำหนดซ้ำๆ ในทุกๆ method
สำหรับการเพิ่ม และแก้ไขข้อมูล เราสมมติตัวแปรข้อมูล เป็นตัวอย่างเท่านั้น ไม่ได้ใช้รูปแบบการส่งค่าจากฟอร์ม
เมื่อเราเรียกไปยัง URL ต่างๆ ก็จะได้ผลลัพธ์ ตามคำอธิบายดังนี้
// แสดงรายการทั้งหมด https://www.mysslweb.com/users // จำลองการเพิ่มรายการข้อมูลใหม่จากตัวแปร https://www.mysslweb.com/users/create // แสดงรายการเฉพาะ id ที่ต้องการ https://www.mysslweb.com/users/view/1 // แก้ไขรายการ id ที่ต้องการ https://www.mysslweb.com/users/edit/1 // ลบรายการ id ที่ต้องการ https://www.mysslweb.com/users/delete/1
รูปแบบและแนวทางการใช้งานข้างต้น เป็นรูปแบบทั่วไปของการใช้งาน Model ใน CI4 ซึ่งมีความยืดหยุ่น เราสามารถกำหนด
การคิวรี่ต่างๆ ได้ตามต้องการ ไม่ว่าจะเป็นการเชื่อมตาราง การคิวรี่ข้อมูลที่มีความซับซ้อน เป็นต้น
สำหรับในกรณีที่เรามีการจัดการข้อมูลในรูปแบบไม่ซับซ้อน เช่น การเพิ่ม ลย แก้ไข ข้อมูลที่ใช้เพียงตารางเดียว หรือการ
งานในรูปแบบ CRUD เบื้องต้น Model ใน CI4 ก็มีเครื่องมือมาให้ โดยที่เราแทบไม่ต้องกำหนดอะไรมากในส่วนของ model
เหมือนตัวอย่างการใช้งานในบทความที่เคยแนะนไปก่อนหน้า ทบทวนได้ที่
สร้างระบบ CRUD เพื่อศึกษาฟังก์ชั่นของ Model ใน CodeIgniter 4 http://niik.in/995
https://www.ninenik.com/content.php?arti_id=995 via @ninenik
เราจะมาดูต่อว่า นอกจากคำสั่งที่เคยแนะนำไปแล้ว ยังมีคำสั่งอื่นๆ ใดอีกบ้างที่เราควรต้องรู้เพิ่มเติม
การเชื่อมต่อฐานข้อมูลใน Model
อย่างที่ทราบกันแล้วว่า เราสามารถเรียกใช้งาน model โดยไม่จำเป็นต้องกำหนดการเชื่อมต่อกับฐานข้อมูล เพราะมีการเชื่อมต่อ
กับฐานข้อมูลด้วยค่าการตั้งค่าที่เป็น default ไว้ให้อยู่แล้ว และสามารถเรียกใช้งานการเชื่อมต่อฐานช้อมูลผ่านตัวแปร $this->db
อย่างไรก็ตาม เราก็สามารถกำหนดการเชื่อมต่อฐานข้อมูลกับการตั้งค่าที่กำหนดเอง เช่น กรณีต้องการเชื่อมต่อไปอีก server หรือ
อีกฐานข้อมูล ก็สามารถกำหนดค่า ชื่อ group ของรูปแบบการตั้งค่าการเชื่อมต่อ ไว้ใน property ที่ชื่อ $DBGroup ได้ประมาณนี้
<?php namespace App\Models; use CodeIgniter\Model; class UsersModel extends Model { protected $DBGroup = 'group_name'; }
โค้ดตัวอย่าง เป็นแนวกาง กรณีต้องการเชื่อมต่อกับฐานข้อมูลที่ไม่ใช่ค่า default หรือเป็นค่าที่กำหนดเองเพิ่มเติม $DBGroup คือ
property ที่ถูกสงานชื่อไว้สำหรับกับค่าส่วนนี้ รูปแบบนี้ มีลักษณะ เหมือนการเรียกใช้งานผ่าน Controller ที่อธิบายไปตอนต้น
<?php namespace App\Controllers; use App\Models\UsersModel; // เรียกใช้งาน Model class use CodeIgniter\Controller; // เรียกใช้งาน Controller class class Users extends Controller { public function index() { $db = db_connect('group_name'); // เพิ่มติม http://niik.in/1001 $userModel = model('UsersModel' , true, $db); } }
แต่แทนที่เราจะกำหนดใน Controller แล้วส่งค่าการเชื่อมต่อเข้ามาใน Model ตอนเรียกใช้งาน เราก็ใช้วิธีกำหนดใน Model
โดยตรงแทน ผ่าน property ที่ชือ $DBGroup
การตั้งค่าการใช้งาน Model
สำหรับการตั้งค่าการใช้งาน model ที่จะใช้กับรูปแบบ CRUD จะกำหนดผ่าน property ต่างๆ ที่สงวนชื่อไว้ให้ เราแค่กำหนด
ค่าตามรูปแบบที่กำหนด โดยทุกๆ CRUD จะต้องมี 2 property นี้เสมอถ้าจะใช้งาน คือ $table และ $primaryKey
เรามาลองปรับการใช้งาน model จากรูปแบบกำหนดเอง มาใช้รูปแบบที่ CI กำหนดมาให้ ก็จะได้ประมาณนี้
App/Models/UsersModel.php
<?php namespace App\Models; // กำหนด namespace use CodeIgniter\Model; // เรียกใช้งาน Model class class UsersModel extends Model // สร้าง Model class โดยสืบทอดจาก Model { protected $table = 'users'; protected $primaryKey = 'id'; protected $allowedFields = ['name', 'email','createdate']; public function getUsers($id = false) { if ($id === false) { return $this->findAll(); } return $this->asArray() ->where(['id' => $id]) ->first(); } }
จะเห็นว่าแบบที่ใช้รูปแบบของ Model กำหนดให้ เราสามารถสร้างแค่ฟังก์ชั่นแสดงข้อมูลเท่านั้นก็พอ ส่วนฟังก์ชั่น เพิ่ม
ลบ แก้ไข ตัว model มีคำสั่งไว้ให้เรียกใช้งานได้เลย อย่างการลบข้อมูลก็มีคำสง delete() คำสั่งแก้ไขข้อมูลก็มี update()
คำสั่งเพิ่มข้อมูลก็มี insert() เป็นต้น
โดยคำสั่งที่ใช้ในการลบข้อมูล ค่า $id ที่ส่งมาลบ จะเป็นข้อมูลของฟิลด์ที่กำหนดใน $primaryKey property ของ model
มาดูการเรียกใช้งานในส่วนของ Controllers
App/Controllers/Users.php
<?php namespace App\Controllers; use App\Models\UsersModel; // เรียกใช้งาน Model class use CodeIgniter\Controller; // เรียกใช้งาน Controller class class Users extends Controller { protected $userModel; public function __construct(){ $this->userModel = model('UsersModel'); } // method สำหรับแสดงข้อมูลทั้งหมด public function index() { $result = $this->userModel->getUsers(); echo "<pre>"; print_r($result); } // method สำหรับแสดงข้อมูล เฉพาะรายการ public function view($id = NULL) { if(!empty($id)){ $row = $this->userModel->getUsers($id); echo "<pre>"; print_r($row); } } // create method สำหรับเพิ่มข้อมูลใหม่ public function create(){ $data = [ 'name' => 'test name '.time(), 'email' => 'test email '.time(), ]; $this->userModel->insert($data); echo "Created!"; } // edit method สำหรับแก้ไขข้อมูล public function edit($id){ $data = [ 'name' => 'edit test name '.time(), 'email' => 'edit test email '.time(), ]; if(!empty($id)){ $this->userModel->update($id, $data); echo "Updated!"; } } // delete method สำหรับลบข้อมูล public function delete($id){ if(!empty($id)){ $this->userModel->delete($id); // ลบข้อมูลจากค่า id ที่เป็น primary key echo "Deleted!"; } } }
ผลลัพธ์การทำงานที่ได้ ก็จะเหมือนกับรูปแบบการทำงานของการกำหนด model เอง แต่วิธีนี้จะสะดวกกว่า เพราะไม่ต้อง
กำหนดอะไรมาใน model
เรามาแยกอธิบายแต่ละ property ของ model กัน โดยยกตัวอย่างรูปแบบ model class ดังนี้
<?php namespace App\Models; use CodeIgniter\Model; class UserModel extends Model { protected $table = 'users'; protected $primaryKey = 'id'; protected $returnType = 'array'; protected $allowedFields = ['name', 'email']; protected $useSoftDeletes = true; protected $dateFormat = 'datetime'; // datetime, date, int protected $useTimestamps = false; protected $createdField = 'created_at'; protected $updatedField = 'updated_at'; protected $deletedField = 'deleted_at'; protected $validationRules = []; protected $validationMessages = []; protected $skipValidation = false; }
$table
เป็น property ที่ใช้กำหนดตารางข้อมูลหลัก ที่จะใช้งานร่วมกับคำสั่ง หรือ method ที่มีมาในระบบ build-in CRUD เท่านั้น
ไม่ได้จำกัดว่า ถ้ากำหนดตารางนี้แล้ว จะใช้ตารางอื่นๆ ร่วมไม่ได้ เรายังสามารถใช้ตารางอื่นๆ หรือกำหนดคำสั่งคิวรี่อื่นตาม
ต้องการได้
$primaryKey
เป็น property ที่ใช้กำหนดคอลัมน์หรือฟิลด์ข้อมูลที่เป็นค่าเฉพาะไม่ซ้ำกัน ปกติก็จะใช้เป็นฟิลด์ที่เป็น primary key หรือ
unique key แต่ไม่ได้จำกัดว่าต้องเป็น primary key จะเป็นฟิลด์ใดๆ ก็ได้ ซึ่งมักใช้งานร่วมกับคำสั่ง find() สำหรับระบุค่าเฉพาะ
ที่ต้องการแสดง
$returnType
เป็น property ที่ใช้กำหนดการคืนค่าข้อมูลที่เป็น Result Object ที่ได้จากคำสั่งของ model เช่น findAll() เราสามารถเลือกได้
ว่าจะให้เป็นแบบ object หรือ array หรือเป็น class object เฉพาะตามต้องการ ค่าเริ่มต้น หากไม่กำหนด ส่วนนี้จะเป็น array
ตัวอย่าง
protected $returnType = 'array'; // array or object or custom class protected $allowedFields = ['name', 'email','createdate']; public function getUsers($id = false) { if ($id === false) { return $this->findAll(); } return $this->where(['id' => $id]) ->first(); }
ค่าที่ return กลับออกไปจะเป็นไปตามที่กำหนดใน $returnType property
$allowedFields
เป็น property ที่กำหนดฟิลด์ที่สามารถทำงานร่วมกับคำสั่ง save() insert() และ update() ฟิดล์ใดๆ ที่ไม่กำหนดในนี้
จะไม่มีผลในการใช้งานร่วมกับคำสั่งข้างต้น ใช้ป้องกันกรณีการส่งข้อมูลจากฟอร์มเข้ามาแล้วเราไม่ต้องการให้ขอมูลนั้นๆ
ไปบันทึกในฟิลด์ที่เราไม่ต้องการ ถึงจะมีข้อมูลส่งมาก็ตาม
property ต่อไปนี้ จะเป็นการกำหนดเกี่ยวกับเวลาให้กับระบบ CRUD ประกอบไปด้วย
protected $useSoftDeletes = true; protected $dateFormat = 'datetime'; // datetime, date, int protected $useTimestamps = false; protected $createdField = 'created_at'; protected $updatedField = 'updated_at'; protected $deletedField = 'deleted_at';
จะกำหนดเมื่อมีการใช้งานเท่านั้น โดยจะมีด้วยกัน 3 ค่าคือ วันเวลาที่เพิ่ม วันเวลาที่แก้ไข วันเวลาที่ลบ
โดยวันเวลาที่เพิ่ม และวันเวลาที่แก้ไข เราจะต้องกำหนดหรือเพิ่มฟิลด์ที่จะให้บันวันที่และเวลาขณะนั้นในฟิลด์ที่กำหนดใน
property ชื่อ $createdField และ $updatedField เราจะลองเพิ่มฟิลด์เข้ามาอีก 2 ฟิลด์โดยใช้ชื่อตามตัวอย่างเลย
และเก็บข้อมูลเป็น DATETIME
จากนั้นกำหนดการใช้งานดังนี้
<?php namespace App\Models; // กำหนด namespace use CodeIgniter\Model; // เรียกใช้งาน Model class class UsersModel extends Model // สร้าง Model class โดยสืบทอดจาก Model { protected $table = 'users'; protected $primaryKey = 'id'; protected $returnType = 'array'; // array or object or custom class protected $allowedFields = ['name', 'email','createdate']; protected $useTimestamps = true; protected $dateFormat = 'datetime'; // datetime or date or int // ค่า defalut เป็น datetime protected $createdField = 'created_at'; protected $updatedField = 'updated_at'; public function getUsers($id = false) { if ($id === false) { return $this->findAll(); } return $this->where(['id' => $id]) ->first(); } }
$useTimestamps
เมื่อเรากำหนดค่านี้เป็น true ระบบ CRUD จะทำการอัพเดทวันเวลาของฟิดล์ created_at ที่กำหนดใน $createdField กรณี
เป็นการเพิ่มข้อมูลใหม่ และจะอัพเดทวันเลาของฟิลด์ updated_at ที่กำหนดใน $updatedField ในกรณีแก้ไขข้อมูล ให้อัตโนมัติ
โดยเป็นวันเวลา ณ ขณะนั้น ชนิดของข้อมูลของฟิลด์ created_at และ updated_at จะต้องสัมพันธ์กับรูปแบบที่กำหนดใน
$dateFormat property ซึ่งข้างต้นเราใช้เป็น datetime ไฟล์ก็ต้องเก็บเป็น DATETIME ด้วย
$useSoftDeletes
property นี้จะมีรูปแบบการใช้งานคล้าย $useTimestamps แต่เป็นการกำหนดวันเวลาให้กับฟิลด์การลบข้อมูลชั่วคร่าว เมื่อใช้
property นี้ต้องกำหนดค่า $deletedField ร่วมด้วย ให้เราเพิ่มฟิดล์ชื่อ deleted_at เข้าไปในตาราง เราจะมาดูว่า ฟิลด์นี้ใช้ทำอะไร
จากนั้นกำหนดการใช้งานใน model เพิ่มเข้าไป
// กำหนดการจัดการส่วนของการ insert() และ update() protected $useTimestamps = true; protected $dateFormat = 'datetime'; // datetime, date, int protected $createdField = 'created_at'; protected $updatedField = 'updated_at'; // กำหนดการจัดการส่วนของการ delete() protected $useSoftDeletes = true; protected $deletedField = 'deleted_at';
การกำหนด $useSoftDeletes เป็น true เป็นการอัพเดทวันเวลาให้กับฟิลด์ deleted_at ที่กำหนดใน $deletedField มีผลให้
รายการข้อมูลที่ถูกลบ จะยังไม่ถูกลบจริงออกจากฐานข้อมูล แต่เวลาแสดงข้อมูลทั้งหมด จะไม่เห็นข้อมูลของรายการที่ถูกลบ
คล้ายๆ กับการลบข้อมูลไปไว้ในถังขยะ ที่เราสามารถกู้คืนได้ ตัวที่ทำให้ข้อมูลไม่แสดงในหน้ารายการทั้งหมดก็คือตัววันเวลา
ที่ถูกอัพเดทในฟิลด์ deleted_at ถ้าเรารีเซ็ตค่านี้ กลับเป็นค่าเดิมหรือค่า '0000-00-00 00:00:00' ข้อมูลก็จะกลับมาแสดงปกติ
ในหน้ารายการทั้งหมด
$validationRules
เป็น property ที่ใช้สำหรับกำหนดรูปแบบการตรวจสอบความถูกต้องของข้อมูล เช่น ข้อมูลอีเมลต้องเป็นรูปแบบอีเมลที่ถูกต้อง
หรือ ข้อมูลที่กำหนดจำนวนตัวอักษรต้องไม่น้อยกว่า 8 ตัวอักษร ประมาณนี้ เป็นต้น โดยค่าที่กำหนด จะอยู่ในรูปแบบ array ค่า
key เป็น ฟิลด์ที่ต้องการตรวจสอบ และ value เป็น รูปแบบการตรวจสอบ หรือค่าจะเป็นข้อความ string ชื่อ validation group ก็ได้
รายละเอียดเพิ่มเติม จะอธิบายด้านล่าง
$validationMessages
เป็น property ที่ใช้กำหนดข้อความ error ที่กำหนดเอง สำหรับใช้งานร่วมกับการตรวจสอบความถูกต้องของข้อมูล อยู้ในรูปแบบ
array รายละเอียดการกำหนดจะเพิ่มเติมในหน้าข้อด้านล่าง
$skipValidation
เป็น property ที่กำหนดว่า เราต้องการจะทำการ validation หรือตรวจสอบความถูกต้องของข้อมูลหรือไม่ ปกติค่า default จะเป็น
true นั่นคือข้อมูลที่กำหนด $validationRules จะถูกตรวจสอบความถูกต้องของข้อมูลตามที่กำหนดไว้เสมอ เว้นแต่เราต้องการยกเลิก
การตรวจสอบ ก็สามารถกำหนดค่าเป็น false
$beforeInsert
$afterInsert
$beforeUpdate
$afterUpdate
$afterFind
$afterDelete
เป็น property ที่เสมือนเป็น event ของ model ความหมายตรงตัว ใช้สำหรับกำหนดคำสั่งหรือฟังก์ชั่น ที่ต้องการให้ทำงาน
เช่น beforeInsert ก็คือทำงานก่อนทำคำสั่ง insert() เป็นต้น ยกตัวอย่าง ก็สมมติว่าเราต้องการให้รหัสผ่าน ถูกเข้ารหัสก่อนบันทึก
เราก็สามารถกำหดชื่อคำสัง method หรือ ฟังก์ชั่น ให้จัดการกับข้อมูลนั้นก่อนที่จะถูกบันทึกด้วยคำสั่ง insert() ได้นั่นเอง
เราจะได้ดูรายละเอียดและตัวอย่าง เพิ่มเติมในหัวข้อด้านล่าง
$allowCallbacks
เป็น property ที่ใช้กำหนดว่า คำสั่งต่างๆ ที่ระบุเรียกใช้งานใน event ของ property ด้านบนทั้ง 6 ให้สามารถทำงานหรือไม่
เช่น สมมติว่า เราทดสอบการทำงาน และยังไม่อยากใช้คำสั่งอื่นๆ ที่กำหนดใน property ทั้ง 6 ข้างบน เราก็กำหนดเป็น false ไป
คือยังไม่ต้องเรียกใช้งาน model events หรือถ้าเราต้องการเรียกใช้งานก็กำหนดเป็น true เป็นต้น
รายละเอียดจะอธิบายเพิ่มเติมในหัวข้อด้านล่าง
การจัดการข้อมูลใน Model
ใน model จะมีคำสั่งสำหรับจัดการข้อมูลต่างๆ ไม่ว่าจะเป็นการค้นหา การแสดงข้อมูล การบันทึก และการลบข้อมูล ให้เราใช้งาน
ได้อย่างสะดวก โดยเฉพาะกับรูปแบบ CRUD ที่เราไม่จำเป็นต้องสร้าง method เพิ่มเติมก็ได้
การค้นหา และแสดงข้อมูล
ประกอบด้วยคำสั่ง และวิธีการใช้งานดังนี้
find()
ใช้สำหรับคืนค่าข้อมูล ตามค่า parameter ที่กำหนด โดยค่า parameter ที่กำหนด จะต้องเป็นค่าของข้อมูลในฟิลด์ที่กำหนด
ไว้ใน $primaryKey property โดยสามารถกำหนดเป็นค่าเดียว หรือ เป็น array ข้อมูลหลายๆ ค่ากรณีต้องการแสดงข้อมูลหลาย
รายการตามค่าที่ส่งไป ดังนี้
กรณีใช้งานใน Model
$this->find(1); // แบบแสดงค่าเดียว $this->find([1,2,3]); // แบบแสดงหลายค่า $this->find(); // ถ้าไม่กำหนด parameter ก็จะแสดงทั้งหมด เหมือนคำสั่ง findAll()
กรณีใช้งานใน Controller
$this->userModel->find(1); $this->userModel->find([1,2,3]); $this->userModel->find();
findColumn()
ใช้สำหรับคืนค่าข้อมูลของฟิลด์ที่ต้องการ รูปแบบการใช้งานจะเป็นดังนี้
findColumn($column_name); // findColumn('id');
คำสั่งข้างต้น จะคืนค่าเป็น array ข้อมูลของฟิลด์ id ดูตัวอย่างการเรียกใช้ใน Controller
public function test(){ $user = $this->userModel->findColumn('id'); echo "<pre>"; print_r($user); // output /* Array ( [0] => 1 [1] => 2 [2] => 4 [3] => 5 [4] => 6 [5] => 7 )*/ }
findAll()
ใช้สำหรับแสดงข้อมูลทั้งหมด ตัวอย่างการใช้งานใน model
public function getUsers($id = false) { if ($id === false) { return $this->findAll(); } return $this->where(['id' => $id]) ->first(); }
เราสามารถใช้งานร่วมกับ Query Builder โดยสามารถกำหนดเงื่อนไขต่างๆ ไว้ด้านหน้า ก่อนใช้คำสั่ง findAll() ดังนี้ได้
$this->where('active', 1) ->findAll();
คำสั่ง findAll() ยังรองรับ parameter 2 ค่า คือ $limit และ $offset เป็นจำนวนรายการที่ต้องการแสดง กับ ตำแหน่งเริ่มต้น
ของแถวรายการที่ต้องการแสดงตามลำดับ ตามรูปแบบดังนี้ findAll($limit, $offset) ตัวอย่างเช่น
$this->findAll(10,20); // แสดงทีละ 10 รายการ โดยเริ่มแถวที่ 21
first()
เป็นคำสั่งสำหรับแสดงรายการเพียงแถวแรกรายการเดียว สามารถใช้งานร่วมกับ query builder ได้ ตัวอย่างเช่น
$this->where('deleted', 0)->first();
withDeleted()
ถ้าเรามีการใช้งาน การกำหนด $useSoftDeletes property เป็น true ซึ่งป็นการลบข้อมูลจากตารางชั่วคราว ไม่ได้ลบออกจริง
เวลาแสดงรายการด้วยคำสั่ง find() หรือ findAll() ข้อมูลก็จะแสดงเฉพาะรายการที่ยังไม่ถูกลบ แต่ถ้าเราต้องการให้แสดงรายที่ถูก
ลบแล้วด้วยก็สามารถใช้คำสั่งนี้แทน
$this->findAll(); // แสดงรายการทั้งหมด ไม่รวมที่ถูกลบชั่วคราว $this->withDeleted()->findAll(); // แสดงรายการทั้งหมด รวมที่ถูกลบชั่วคราวด้วย
onlyDeleted()
รูปแบบตรงกันข้ามกับคำสั่งก่อนหน้า ตัวนี้ใช้สำหรับแสดงรายการที่ถูกลบชั่วคราวเท่านั้น
$this->onlyDeleted()->findAll(); // แสดงเฉพาะรายการที่ถูกลบชั่วคราว
การบันทึกข้อมูล
ประกอบด้วยคำสั่ง และวิธีการใช้งานดังนี้
insert()
เป็นคำสั่งที่ใช้สำหรับบันทึก หรือการเพิ่มข้อมูลใหม่ น่าจะคุ้นตาจากตัวอย่างด้านบนไปบ้างแล้ว
key ของ array เป็นฟิลด์ของตารางที่กำหนดใน $table property
$data = [ 'name' => 'test name '.time(), 'email' => 'test email '.time(), ]; $this->userModel->insert($data);
update()
เป็นคำสั่งที่ใช้สำหรับอัพเดทหรือแก้ไขข้อมูล โดยจะมีการกำหนด parameter แรกเป็น ค่า ของ $primaryKey ที่ต้องการ
และ parameter ตัวที่สองเป็นเป็นข้อมูลที่จะแก้ไขหรืออัพเดท
$data = [ 'name' => 'edit test name '.time(), 'email' => 'edit test email '.time(), ]; $this->userModel->update($id, $data);
กรณีเราต้องการอัพเดทค่าเดียวกัน ให้กับ id หรือ $primaryKey หลายๆ ค่าพร้อมกัน ก็สามารถกำหนด parameter แรก เป็น
array ของค่า id ที่ต้องการได้ เช่น
$data = [ 'active' => 1 ]; $this->userModel->update([1, 2, 3], $data);
เราสามารถใช้งานร่วมกับ query builder โดยอาจจะละค่า parameter ไป แล้วกำหนดเป็นส่วนเพิ่มเติม ในกรณีต้องการปรับ
แต่งค่าใดค่าหนึ่งก็สามารถทำได้ดังนี้
$this->userModel ->whereIn('id', [1,2,3]) ->set(['active' => 1]) ->update(); // อัพเดท id เท่ากับ 1,2 และ 3 กำหนดค่า active เป็น 1
save()
ใช้ทำงานในรูปแบบที่ได้ทั้ง insert() และ update() โดยขึ้นกับข้อมูลที่บันทึก เข่น กรณีต้องการให้เป้นการเพิ่มข้อมูลใหม่
หรือทำคำสั่ง insert() ก็ให้ละ key ที่เป็น $primaryKey ส่วนกรณีที่ต้องการให้เป็นการอัพเดท ก็ให้กำหนด key ที่เป็น
$primaryKey เข้าไปด้วย ดูตัวอย่างด้านล่างประกอบ
// กำหนด property ของ model $primaryKey = 'id'; // insert() $data = [ 'username' => 'darth', 'email' => 'd.vader@theempire.com' ]; $this->save($data); // update() , เมื่อกำหนด primary key, 'id' $data = [ 'id' => 3, 'username' => 'darth', 'email' => 'd.vader@theempire.com' ]; $this->save($data);
การลบข้อมูล
ประกอบด้วยคำสั่ง และวิธีการใช้งานดังนี้
delete()
ใช้สำหรับลบข้อมูล โดยกำหนด parameter แรกเป็นค่าของข้อมูล ที่กำหนดใน $primaryKey property
$this->delete(1);
ในกรณีที่มีการใช้งานการกำหนด $useSoftDeletes เป็น true หรือการลบข้อมูลชั่วคราว ข้อมูลจะยังไม่ถูกลบออกจากตาราง
จริง หากต้องการลบข้อมูลถาวรโดยลบออกจากตารางเลย สามารถเพิ่ม parameter ตัวที่สองเป็น true
$this->delete(1, true); // กรณี $useSoftDeletes เป็น true และต้องการลบแบบถาวร
สามารถลบหลายรายการพร้อมกัน โดยใช้ค่าเป็น array
$this->delete([1,2,3]);
สามารถใช้ร่วมกับ query builder และไม่จำเป็นต้องกำหนด parameter โดยตรง แต่เปลี่ยนเป็นกำหนดในเงื่อนไข where()
$this->where('id', 12)->delete();
purgeDeleted()
ใช้สำหรับลบข้อมูลของตารางนั้นทั้งหมดอย่างถาวร โดยมีฟิลด์ deleted_at มีค่าไม่เท่ากับ NOT NULL เหมือนกับลบ
รายการที่ถูกลบชั่วคราวออกให้หมด
$this->purgeDeleted();
การตรวจสอบความถูกต้องของข้อมูล Validating Data
การตรวจสอบความถูกต้องของข้อมูล สามารถจัดการได้ทั้งใน Controller และ Model แต่ส่วนใหญ่จะนิยม
ใช้งานใน Model เพราะถ้าใช้งานใน model เลย เราก็จะจัดการข้อมูลได้ง่าย ไม่ต้องสลับการทำงานระหว่าง
Controller และ Model มากนัก แต่อย่างไรก็ตามขึ้นอยู่กับความสะดวกของแต่ละคน จะใช้แบบใดก็ได้
ใน Model class จะมีการตรวจสอบความถูกต้องของข้อมูลให้อัตโนมัติก่อนที่จะถูกบันทึกด้วยคำสั่ง insert()
update() หรือ save() เมื่อเราได้กำหนด $validationRules ไว้
เกี่ยวกับการกำหนด Validation Rules จะมีหัวข้อแยกย่อยเพิ่มเติมอีกในบทความภายหลัง ในที่นี้ จะให้เห็น
การใช้งานคร่าวๆ เบื้องต้น โดยเฉพาะการเรียกใช้งานใน Model ไปก่อน
จะขอเรียกการตรวจสอบความต้องของข้อมูลด้วยคำว่า validated data แทน
ในการ validated data ใน model เริ่มต้นให้เราทำการกำหนดค่า validation rules ให้กับ $validationRules
property ที่ก่อน โดยจะเป็นลักษณะของ array ที่ key เป็นฟิลด์ข้อมูลที่จะใช้งาน และ value เป็นรุปแบบ rules
ที่จะใช้ในการตรวจสอบ โดยสามารถกำหนดได้หลายรูปแบบคั่นด้วย | ดูตัวอย่างการกำหนดด้านล่าง
class UsersModel extends Model { protected $validationRules = [ 'username' => 'required|alpha_numeric_space|min_length[3]', 'email' => 'required|valid_email|is_unique[users.email]', 'password' => 'required|min_length[8]', 'pass_confirm' => 'required_with[password]|matches[password]' ]; protected $validationMessages = [ 'email' => [ 'required' => 'Sorry. That email is Required.', 'is_unique' => 'Sorry. That email has already been taken. Please choose another.' ] ]; }
ดูส่วนของ email จะเห็นว่า email คือฟิลด์ข้อมูลที่เราจะตรวจสอบ และ ค่า required, valid_email และ
is_unique[users.email] คือ rules รูปแบบของ CI มีมาให้แล้ว ที่เราใช้ในการตรวจสอบ
ในตัวอย่าง ปกติแล้วถ้าสมมติข้อมูล email ไม่ผ่านการตรวจสอบ หรือข้อมูลไม่ถูกต้อง ก็จะมีข้อความ error
แจ้งในรูปแบบที่ CI กำหนดมาให้ แต่เราก็สามารถกำหนดรูปแบบของข้อความที่ต้องการแสดงได้เอง โดยกำหนด
ค่าใน $validationMessages ตามตัวอย่างในรูปแบบด้านบน เช่น email ถ้าเป็น rule ชื่อว่า is_unique ก็กำหนด
ข้อควาามตามตัวอย่าง เป็นต้น
กรณีที่เรามีการจัดการ rules และ error ไว้ในไฟล์ app/Config/Validation.php เพื่อที่จะสามารถเรียกใช้งาน
จาก model หรือที่ต่างๆ ใน CI ได้ง่าย เราก็อาจจะใช้ชื่อของ validation rule group ที่เรากำหนด มากำหนดค่า
แทนการกำหนดเป็นแบบ array ก็ได้ สมมติว่าเรากำหนดชื่อ rule group ไว้สำหรับตรวจสอบข้อมูล users
โดยเฉพาะ และใช้ชื่อว่า 'users' เราก็กำหนดเป็นดังนี้
class UsersModel extends Model { protected $validationRules = 'users'; }
การกำหนด validated data ไว้ใน Model ข้างต้นแล้ว เราไม่ต้องกำหนดคำสั่งอะไรเพิ่มเติมใน model เพื่อใช้งาน
เพราะตัว model จะจัดการทุกอย่างให้อัตโนมัติ เราแค่ใช้งานการตรวจสอบความถูกต้องของข้อมูล ใน Controller
ในส่วนของการเรียกใช้งานคำสั่ง insert() update() หรือ save() ของ model แล้วใช้ค่า $model->errors()
ส่งไปแสดงผลใน Views กรณีมี error เกิดขึ้น
ตัวอย่างการใช้งาน
if ($this->userModel->save($data) === false) { return view('updateUser', ['errors' => $this->userModel->errors()]); }
ข้างต้นเราใช้กับคำสั่ง save() ถ้าทำการบันทึกแล้ว คืนค่าเป็น false แสดงว่า การ validated data ไม่ผ่าน เรา
สามารถใช้งาน คำสั่ง error() ของ model เพื่อส่งข้อความหรือข้อผิดพลาดไปแสดงข้อมูลใน views ได้ตามตัวอย่าง
ค่า error ที่คืนกลับมาจะเป็นค่า ฟิลด์ข้อมูล กับข้อความ error ที่สัมพันธ์กัน ซึ่งเราสามารถนำไปแสดงด้านบนสุด
ของฟอร์มที่เดียว หรือจะแสดงแต่ละจุดของข้อมูลนั้นๆ ที่ไม่ผ่านการตรวจสอบก็ได้ ดูตัวอย่างการใช้งาน Views
<?php if (! empty($errors)) : ?> <div class="alert alert-danger"> <?php foreach ($errors as $field => $error) : ?> <p><?= $error ?></p> <?php endforeach ?> </div> <?php endif ?>
ตัวอย่างข้างบน เป็นการตรวจสอบว่ามี error เกิดขึ้นหรือไม่จากตัวแปร $errors ที่ส่งมา ถ้ามีก็วนลูปแสดง error
ทั้งหมดเป็นรายการ ว่าฟิลด์ไหนบ้าง และ error ข้อความว่าอะไร เป็นต้น
การกำหนด validated data โดยใช้วิธีกำหนดใน $validationRules และ $validationMessages property ข้างต้น
ทำให้เราสามารถจัดการการตรวจสอบข้อมูลไว้ที่เดียวใน model แต่บางครั้ง เราอาจจำเป็นต้องปรับหรือกำหนดการ
ตรวจสอบเฉพาะเพิ่มเติม ใน Controller ในบางค่า หรือบางข้อมูล เราก็สามารถเลือกที่จะกำหนดการ validated data
เพิ่มเติมได้ ผ่านคำสั่งต่างๆ ดังนี้
setValidationRule($field, $fieldRules)
ใช้กำหนด rules เป็นรายการๆ ไป ตามต้องการ เช่น
$fieldName = 'username'; $fieldRules = 'required|alpha_numeric_space|min_length[3]'; $this->userModel->setValidationRule($fieldName, $fieldRules); if ($this->userModel->save($data) === false) { return view('updateUser', ['errors' => $this->userModel->errors()]); }
setValidationRules($validationRules)
ใช้กำหนด rules แบบ array
$validationRules = [ 'username' => 'required|alpha_numeric_space|min_length[3]', 'email' => [ 'rules' => 'required|valid_email|is_unique[users.email]', 'errors' => [ 'required' => 'We really need your email.', ], ], ]; $this->userModel->setValidationRules($validationRules); if ($this->userModel->save($data) === false) { return view('updateUser', ['errors' => $this->userModel->errors()]); }
setValidationMessage($field, $fieldMessages)
เช่นเดียวกันกับรูปแบบการกำหนดข้อความ error แบบกำหนดเอง ก็สามารถกำหนดข้อความให้แต่ละรายการได้
$fieldName = 'name'; $fieldValidationMessage = [ 'required' => 'Your name is required here', ]; $this->userModel->setValidationMessage($fieldName, $fieldValidationMessage);
setValidationMessages($fieldMessages)
ใช้กำหนด error ข้อความ แบบ array
$fieldValidationMessage = [ 'name' => [ 'required' => 'Your baby name is missing.', 'min_length' => 'Too short, man!', ], ]; $this->userModel->setValidationMessages($fieldValidationMessage);
การใช้ค่า Validation Rules
ปกติ เมื่อเรากำหนด $validationRules ใน model แล้ว เราสามารถใช้งานการ validated data อัตโนมัติ จาก
ค่าที่กำหนด แต่สมมติว่า เราต้องการใช้ validation rule ที่กำหนดมาใช้งานบางอย่างต่อ หรือเลือกมาใช้งานเฉพาะ
บางรายการเท่านั้น ไม่ได้ใช้ทั้งหมด เราก็สามารถใช้คำสั่งต่อไปนี้ เรียกค่า validation rules มาใช้ได้
$rules = $this->userModel->validationRules; // จะได้ค่า validation rules ทั้งหมด ที่กำหนดใน model มาใช้
ถ้าเราต้องการเฉพาะบางฟิลด์ข้อมูล หรือเอาทุกฟิลด์ข้อมูลยกเว้นบางฟิลด์ ก็สามารถกำหนด option เป็น
parameter แรกเข้าไป ตามรูปแบบดังนี้ได้
// กรณีเอาทั้งหมด ยกเว้น ฟิลด์ "username" $rules = $this->userModel->getValidationRules(['except' => ['username']]); // กรณีเอาเฉพาะฟิลด์ "city" และ "state" $rules = $this->userModel->getValidationRules(['only' => ['city', 'state']]);
เมื่อได้เฉพาะฟิลด์ที่ต้องการ เราก็สามารถเอาไปกำหนดในการ validated data ด้วยคำสั่ง
$rules = $model->getValidationRules(['except' => ['username']]); $this->userModel->setValidationRules($rules);
การแทนที่ค่า Validation Rules
ในการ validated data บางรูปแบบของ rules เราอาจจำเป็นต้องส่งข้อมูลฟิลด์และค่าของข้อมูลนั้นๆ ไปเป็น
เงื่อนไขหรือข้อยกเว้น เช่น การใช้งาน is_unique ดูตัวอย่างการกำหนดด้านล่างประกอบ
protected $validationRules = [ 'email' => 'required|valid_email|is_unique[users.email,id,{id}]' ];
การตรวจสอบ email โดยไม่ให้ค่าซ้ำข้างต้น ใช้รูปแบบเช็คค่าจากตาราง users ที่ฟิลด์ email ซึ่งปกติเราก็กำหนด
แค่รูปแบบดังนี้ is_unique[users.email] ตัวตรวจสอบก็ขจะทำการเช็คฟิลด์ email ทั้งหมดว่ามีค่า email ที่ส่งมาเช็ค
อยู่แล้วหรือไม่ แต่บางครั้ง เราต้องการเงื่อนไขเพิ่มเติมว่า ไม่ต้องเช็คแถวข้อมูลที่มี id = 4 เราก็เพิ่มรูปแบบการตรวจ
สอบเพิ่มเติม โดยระบุ ชื่อฟิลด์ข้อมูล และ validation placeholder หรือตำแหน่งสำหรับแทนที่ค่าข้อมูลเข้าไปไว้ใน
วงลบปีกา ดังนี้ is_unique[users.email,id,{id}] นั่นคือ เมื่อมีการส่งข้อมูลค่า id เข้ามา ค่า id นั้นก็จะถูกแทนที่ใน
รูปแบบของ rules ที่ตำแหน่ง {id} ให้อัตโนมัติ
สมมติข้อมูล $_POST ส่งมาเป็นแบบนี้
$_POST = [ 'id' => 4, 'email' => 'foo@example.com' ];
ตำแหน่งของ {id} ก็จะถูแทนที่ด้วยเลข 4 จะมีค่าเหมือนกับการกำหนดตรงตัวดังนี้
protected $validationRules = [ 'email' => 'required|valid_email|is_unique[users.email,id,4]' ];
การตรวจสอบข้อมูล email ก็จะไม่พิจารณา email ในแถวข้อมูลที่มี id = 4 นั่นคือถ้า email ซ้ำกับแถวข้อมูล
ที่มี id=4 ก็ยังผ่านเงื่อนไขได้
การป้องกันฟิลด์ข้อมูล
อย่างที่เราทราบไปแล้วว่า การกำหนด $allowedFields property ใน model เป็นการกำหนดว่า ฟิลด์ใดบ้างใน
ตารางที่กำหนดใน $table ที่สามารถบันทึกข้อมูลได้
protected $allowedFields = ['name', 'email', 'address'];
แต่บางครั้ง เราอาจจำเป็นต้องการยกเลิกการป้องกันนั้นๆ ในระหว่างทดสอบระบบ หรือการปรับเปลี่ยนบางอย่าง
ชั่วคราว เราสามารถปิดการป้องกันชั่วคราว ในขั้นตอนการบันทึกข้อมูล ได้ดังนี้
$this->userModel->protect(false) ->insert($data) ->protect(true);
โดยใช้คำสั่ง protect() ของ model แล้วกำหนด parameter เป็น false ก่อนทำการบันทึกข้อมูล และกำหนด
ค่ากลับหากต้องการป้องกันเหมือนเดิม หลังบันทึกข้อมูลเรียบร้อยแล้ว
การใช้งานร่วมกับ Query Builder
เราสามารถเรียกใช้งาน Builder จากการเชื่อมต่อฐานข้อมูลของ model ได้ด้วยคำสั่ง builder() ดังนี้
$builder = $this->userModel->builder();
จะมีค่าเหมือนการเรียกใช้งาน builder แบบปกติ ที่ใช้เป็น $db->table('users'); แต่ในการใช้งาน ร่วมกับ
model จะเป็นการใช้งานกับตาราง ที่กำหนดใน $table
นอกจากนั้น เรายังสามารถเรียกใช้คำสั่งของ builder ได้โดยตรงจาก model instance ร่วมกับคำสั่งของ
model อย่าง find() findAll() first() ได้ง่าย โดยกำหนดเรียกใช้ไว้ด้านหน้าของคำสั่งเหล่านี้
$users = $this->userModel->where('status', 'active') ->orderBy('last_login', 'asc') ->findAll();
และยังสามารถใช้คำสั่ง escape() ข้อมูลของ builder ได้ด้วย
$user_name = $userModel->escape($name);
การกำหนดชนิดข้อมูลที่คืนค่าขณะทำงาน
การกำหนด $returnType เป็น array หรือ object จะทำให้สามารถกำหนดชนิดหรือรูปแบบของข้อมูลที่คืนกลับ
จากการใช้งานคำสั่งต่างๆ ของ model แต่บางครั้ง ในระหว่างการทำงาน เราออาจจะอยากเปลี่ยนรูปแบบการคืนค่า
ของข้อมูล ณ ขณะเรียกใช้งานในเวลานั้นๆ ชั่วคราว เป็นรูปแบบที่เราต้องการ ก็สามารถใช้คำสั่งเหล่านี้ กำหนด
รูปแบบของข้อมูลที่ต้องการได้
asArray()
ใช้สำหรับคืนค่าข้อมูลเป็นแบบ array
$users = $this->userModel->asArray()->where('status', 'active')->findAll();
asObject()
ใช้สำหรับคืนค่าข้อมูลเป็นแบบ object
// แบบ standard objects $users = $this->userModel->asObject()->where('status', 'active')->findAll(); // แบบ custom class instances $users = $this->userModel->asObject('User')->where('status', 'active')->findAll();
การจัดการข้อมูลจำนวนมาก
ในการจัดการข้อมูลจำนวนมาก บ่อยคร้้งอาจจะทำให้มีการใช้งานหน่วยความจำ จำนวนมากเพิ่มขึ้นด้วย ดังนั้น
เราสามารถเลือกจะ แยกข้อมูลที่มีจำนวนมากๆ เป็นส่วนๆ แล้วจัดการทีละส่วนแทน โดยใช้คำสั่ง chunk() และระบุ
parameter แรกเป็นจำนวนแถวของรายการที่จะจัดการแต่ละครั้ง และ paramter ตัวที่สองเป็นข้อมูลที่ใช้งาน
ดูตัวอย่างการกำหนด ดังนี้
$this->userModel->chunk(100, function ($data) { // do something. // $data ข้อมูลของรายการแต่ละแถว });
มักใช้จัดการกับข้อมูลจำนวนมากๆ ในการทำงานอย่าง cronjob , การ export ข้อมูล หรือการทำงานที่มีรูปแบบ
การจัดการที่ซับซ้อน
การใช้งาน Model Events
ในการจัดการข้อมูลต่างๆ ใน model จะมีหลายๆ จุดที่เราสามารถกำหนดการทำงาน หรือการจัดการกับข้อมูลได้ เช่น
ต้องการปรับเปลี่ยนรูปแบบของข้อมูล อย่างเช่น ข้อมูลรหัสผ่าน ก่อนบันทึก เราต้องการให้ทำการเข้ารหัสก่อน หรือกรณี
ทำการเพิ่มข้อมูลเรียบร้อยแล้ว เราต้องการอัพเดทข้อมูลหลังจากเพิ่มข้อมูล แบบนี้เป็นต้น การกำหนดจุดตำแหน่งการ
ทำงานข้างต้น เราจะทำผ่านการกำหนดฟังก์ชั่นหรือคำสั่้งให้กับ property ต่างๆ ดังนี้
$beforeInsert, $afterInsert, $beforeUpdate, $afterUpdate, $afterFind, และ $afterDelete.
หากพิจารณาจากชื่อของ property เราก็พอจะเดาได้ว่า การทำงานต่างๆ จะเกิดขึ้นตอนไหน สิ่งที่เราต้องทำก็คือสร้าง
คำสั่ง method หรือฟังก์ชั่นที่จะกำหนดใช้งาน และกำหนดค่าไปที่ property ที่จะใช้
การกำหนดฟังก์ชั่น Callback
เพื่อให้เราสามารถเรียกใช้งานคำสั่งที่ต้องการได้ เราต้องสร้างฟังก์ชั่นหรือคำสั่งนั้นขึ้นมาก่อน ตามรูปแบบการใช้งาน
ยกตัวอย่าง เราต้องการให้ข้อมูลที่เป็น รหัสผ่าน ที่ถูกส่งเข้ามาบันทึก ต้องถูกเข้ารหัสก่อน ก็จะกำหนด method ใน
model เพื่อใช้งานดังนี้
protected function hashPassword(array $data) { if (! isset($data['data']['password']) return $data; $data['data']['password_hash'] = password_hash($data['data']['password'], PASSWORD_DEFAULT); unset($data['data']['password']; return $data; }
method ที่กำหนดจะต้องมีข้อมูลจากตัวแปร array $data ถูกส่งเข้ามาเสมอ และจะอ้างอิงค่าข้อมูลจาก key ที่ชื่อว่า
data อย่างตัวอย่างด้านบน ข้อมูลรหัสผ่าน ก็ผ่านตัวแปร $data['data']['password'] คือข้อมูลอ้างอิงฟิลด์ password
ที่ถูกส่งเข้ามา หลังข้อมูลถูกส่งเข้ามาแล้วจัดรูปแบบเรียบร้อยแล้ว เราก็สามารถกำหนดโดยใช้ชื่อใหม่ เพื่อส่งกลับออกไป
โดยจะส่งกลับออกไปในรูปแบบเดิมคือตัวแปร $data['data'] และกำหนดฟิลด์ข้อมูลตามต้องการ ข้างต้น กำหนดให้
ชื่อที่ส่งออกไปเป็น $data['data']['password_hash'] เป็นข้อมูลรหัสผ่านที่เข้ารหัสแล้ว ข้อมูลนี้ก็จะถูกนำไปบันทึก
ลงฐานข้อมูลในลำดับต่อไป
การเรียกใช้ฟังก์ชั่น Callback
เมื่อกราสร้างฟังก์ชั่นที่จะใช้งานแล้ว ก็ถึงขึ้นตอนที่จะบอกให้คำสั่งนั้นๆ ถูกเรียกใช้งานเมื่อใด ซึ่งข้างต้น เราจะใช้งาน
ก่อนบันทึกข้อมูล ทั้งการเพิ่มและการแก้ไขข้อมูล เราก็กำหนดคำสั่ง hashPassword ไปใน $beforeInsert และ
$beforeUpdate ตามรูปแบบดังนี้
protected $beforeInsert = ['hashPassword']; protected $beforeUpdate = ['hashPassword'];
เราสามารถกำหนดหลายๆ คำสั่งใน property เดียวกันได้ โดยการทำงานก็จะทำคำสั่งแรกเสร็จก็ทำคำสั่งที่สอง สมมติ
เช่น ก่อนเพิ่มข้อมูล นอกจากเราจะจัดการกับรูปแบบของรหัสผ่านที่ต้องเข้ารหัสแล้ว เราอาจจะจัดรูปแบบของเบอร์โทรด้วย
ถ้า สมมติคำสั่งในการจัดรูปแบบของเบอร์โทรเป็น formatTel เราก็ระบุเป็นประมาณนี้
protected $beforeInsert = ['hashPassword','formatTel'];
โดยค่าเริ่มต้นแล้ว คำสั่งต่างๆ ที่กำหนดใน model event ก็จะทำงานโดยอัตโนมัติ แต่กรณีที่เราต้องการปิดการทำงาน
ชั่วคราว หรือไม่ต้องการใช้งานก็สามารถกำหนด $allowCallbacks property เป็น false ได้ ดังนี้
protected $allowCallbacks = false;
การกำหนดค่าเป็น false ข้างต้น จะเป็นการปิด model ทั้งหมด แต่ถ้าเราไม่ต้องการปิดทั้งหมด ต้องการปิดเฉพาะ บาง
คำสั่งหรือบาง event ก็สามารถใช้คำสั่ง allowCallbacks(false) ในขึ้นตอนการเรียกใช้งาน ณ ขณะเวลานั้นได้ ดังนี้
$this->userModel->allowCallbacks(false)->find(1); // หากมีการกำหนดคำสั่้งในส่วนของ $afterFind คำสั่งนั้นจะไม่ทำงานชื่อคราว // เพราะเราปิดการเรียกใช้ชั่วคราวผ่านคำสั่ง allowCallbacks(false) $this->userModel->find(1); // คำสั่้งในส่วนของ $afterFind ถ้ามีการกำหนดค่าไว้
Event Parameters
รายละเอียดต่อไปนี้ เป็นข้อมูลค่าของ $data parameter ที่ถูกส่งไปยังในแต่ละ event
beforeInsert
data = ข้อมูล array รูปแบบ key/value ที่จะถูกบันทึก
afterInsert
id = ค่า primary ของข้อมูลที่แถวที่เพิ่งบันทึกไป หรือ 0 กรณีไม่สำเร็จ
data = ข้อมูล array รูปแบบ key/value ที่บันทึก
result = ผลลัพธ์ของคำสั่ง insert() ที่ใช้งานผ่าน query builder
beforeUpdate
id = ค่า primary ของแถวรายการที่จะอัพเดท
data = ข้อมูล array รูปแบบ key/value ที่จะอัพเดท
afterUpdate
id = ค่า primary ของแถวรายการที่ได้อัพเดท
data = ข้อมูล array รูปแบบ key/value ที่อัพเดท
result = ผลลัพธ์ของคำสั่ง update() ที่ใช้งานผ่าน query builder
afterFind
มีค่า parameter ขึ้นกับรูปแบบคำสั่งที่ใช้งานดังนี้
find()
id = ค่า primary ของแถวรายการที่ค้นหา
data = ผลลัพธ์แถวรายการข้อมูล หรือ null ถ้าไม่พบข้อมูล
findAll()
data = ผลลัพธ์แถวรายการข้อมูล หรือ null ถ้าไม่พบข้อมูล
limit = จำนวนแถวรายการที่พบ
offset = จำนวนแถวรายการที่ข้ามไม่รวมในการค้นหา
first()
data = ผลลัพธ์แถวรายการข้อมูล หรือ null ถ้าไม่พบข้อมูล
beforeDelete
delete()
id = ค่า primary ของแถวรายการที่จะถูกลบ
purge = ค่า true / false ที่จะระบุว่าเป็นการลบแบบถาวร หรือชั่วคราว
afterDelete
delete()
id = ค่า primary ของแถวรายการที่ถูกลบ
purge = ค่า true / false ที่จะระบุว่าเป็นการลบแบบถาวร หรือชั่วคราว
result = ผลลัพธ์ของคำสั่ง delete() ที่ใช้งานผ่าน query builder
data = รายการข้อมูลที่ไม่ได้ใช้งาน
การสร้าง Model แบบกำหนดเอง
ในการใช้งาน model ใน CI ปกติแล้ว เราจะทำการ extend มาจาก model class ของ CI ซึ่งมี property และคำสั่ง
ต่างๆ มาให้ แต่ถ้าเราไม่อยากใช้คำสั่ง หรือรูปแบบของ model ที่ CI จัดให้ ในบางไฟล์ model เราสามารถสร้างรูปแบบ
model ที่ไม่ยึดติดกับรูปแบบของ CI ได้ ทำให้เราสามารถจะกำหนดฟังก์ชั่ชื่อ insert() upate() save() และอื่นๆ ได้
ตามรูปแบบที่ตัวเองกำหนดได้ เพียงแต่ในการกำหนดเองนี้ เราจะต้องกำหนดการเชื่อมต่อฐานข้อมูลเข้ามาด้วยเท่านั้น
สมมติเรากำหนด UsersModel.php แบบกำหนดเอง จะได้เป็น
app/Models/UsersModel.php
<?php namespace App\Models; use CodeIgniter\Database\ConnectionInterface; class UsersModel { protected $db; public function __construct(ConnectionInterface &$db) { $this->db =& $db; } }
ในการใช้งานใน Controller เราก็ทำการส่งการเชื่อมเข้ามาใช้งานตอนเรียกใช้ model ดังนี้
app/Controllers/Users.php
<?php namespace App\Controllers; use App\Models\UsersModel; use CodeIgniter\Controller; // เรียกใช้งาน Controller class class Users extends Controller { public function index() { $db = db_connect(); $userModel = model('UsersModel', true, $db); } }
เท่านี้เราก็สามารถกำหนดการทำงานของ model ได้ตามต้องการ
หวังว่าเนื้อหาเกี่ยวกับการใช้งาน model ใน CI4 จะเป็นแนวทางทำความเข้าใจ และนำไปประยุกต์ใช้ต่อไปได้