เนื้อหาตอนที่แล้ว เราพูดถึง Routes ซึ่งเป็นการกำหนด
URL ของหน้าเพจที่ต้องการแสดงใน CI4 โดยในการใช้งาน
Routes ก็จะมีการเรียก Controller class และ Controller method
ทบทวนตอนที่แล้วได้ที่
ทำความรู้จักกับ URL และ URI Routing ใน CodeIgniter 4 http://niik.in/996
https://www.ninenik.com/content.php?arti_id=996 via @ninenik
เนื้อหาตอนต่อไปนี้ เราจะมาดูว่า Controller คืออะไร และสำคัญอย่างไรใน CI4
ถึงแม้ว่าเราจะมีอธิบายไปแล้วพอสมควรเเกี่ยวกับ Controller แต่ในที่นี้ จะขอเริ่มต้นอธิบาย
ตั้งแต่แรก เพื่อทบทวนทำความเข้าใจเพิ่มเติมอีกครั้ง
Controller คืออะไร
ใน CI นั้น Controller ก็คือรูปแบบ class ที่ถูกรียกใช้งานสอดคล้องหรือสัมพันธ์กับ URL ลองดูตัวอย่างดังนี้
example.com/index.php/helloworld/
เมื่อเราเรียกไปยัง URL ข้างต้น CI ก็จะทำการหาชื่อ Controller ไฟล์ Helloworld.php และทำการโหลดมาใช้งาน
นั่นคือ ถ้ามีชื่อ Controller ไฟล์ไหนตรงกับ segment แรกของ URL ก็จะถูกโหลดมาใช้งาน
* ในเนื้อหาเราจะขอตัดส่วนของ index.php ออก ตามที่ได้อธิบายไปแล้วในหัว Routing http://niik.in/996
** เนื่องจากเป็นการเริ่มต้นทำความเข้าใจ Controller หากเราได้กำหนด Routes ตามบทความก่อนหน้า ให้เราคง
การกำหนดค่า rule สำหรับ Routes ไว้เพียงค่าเดียวคือ
$routes->get('/', 'Home::index');
ส่วนการกำหนดอื่นๆ ให้ลบ หรือ comment ปิดไปก่อนได้
เริ่มต้นกับ Hello World!
ให้เราสร้างไฟล์ controller อย่างง่าย เพื่อดูการทำงาน ชื่อไฟล์ว่า Helloworld.php ใน โฟลเดอร์ App/Controllers
และกำหนดโค้ดเบื้องต้นดังนี้ลงไป
App/Controllers/Helloworld.php
<?php namespace App\Controllers; // กำนหด namespace คล้ายๆ กำหนด path ของไฟล์นี้ use CodeIgniter\Controller; // เรียกใช้งาน Controller class class Helloworld extends Controller // สร้าง Helloworld สืบทอดจาก Controller class { public function index() // กำหนด method ใน CI index() method จะเป็นค่าเริ่มต้น { echo 'Hello World!'; // ทดสอบแสดงผล } }
* การกำหนดชื่อไฟล์ของ Controller จะต้องขึ้นต้นด้วยตัวพิมพ์ใหญ่เสมอ
เช่นเดียวกัน กับการกำหนดชื่อ class จะต้องมีเฉพาะตัวแรกที่เป็นตัวพิมพ์ใหญ่ ตัวเดียวเท่านั้น
class Helloworld extends Controller // ถูกต้อง class helloworld extends Controller // ไม่ถูกต้อง class HelloWorld extends Controller // ไม่ถูกต้อง
เมื่อเราทดสอบเรียกไปยัง URL example.com/helloworld/ ก็จะแสดงข้อความว่า "Hello World!"
การที่หน้าเพจ สามารถแสดงข้อความข้างต้นได้ ทั้งที่เรายังไม่ได้ไปกำหนด Routes ก็เพราะว่ามีการกำหนด
$routes->setAutoRoute(true); // เนื้อหาในตอนที่แล้ว http://niik.in/996
ในกรณีที่ไม่กำหนด Routes หรือ ไม่มี rule ของ Routes ที่ตรงกับรูปแบบ URL ที่เรียกใช้งาน ระบบจะพยายาม
จับคู่ค่า segment ของ URL ให้สอดคล้องกับไฟล์ controller ในรูปแบบ folders/files โดยอ้างอิงจาก
APPPATH/Controllers หรือก็คือโฟลเดอร์ตาม path app/Controllers นั่นเอง จึงเป็นเหตุผลว่าทำไม เราต้องกำหนดตัวแรก
ของไฟล์เป็นพิมพ์ตัวใหญ่ และส่วนที่เหลือเป็นตัวพิมพ์เล็กทั้งหมด
การกำหนด Method
ในตัวอย่างด้านบน จะเห็นว่า index() method จะเป็น method เรื่มต้นที่ถูกโหลดมาใช้งาน ซึ่งสัมพันธ์กับ URL ใน segment
ตัวที่สองในกรณีเป็นค่าว่าง แต่ถ้าเรากำหนด segment ที่สองเป็นค่าอื่น ก็จะหมายถึงไปเรียก method นั้นๆ มาใช้งาน
example.com/index.php/helloworld/ example.com/index.php/helloworld/index/
การเรียกไป URL ทั้งสอง ให้ผลลัพธ์เหมือนกัน เพราะ segment ตัวที่สอง ของทั้งสอง URL เป็นการเรียกใช้ index() method
แม้ตัวแรกไม่ได้กำหนดค่าลงไปหรือเป็นค่าว่าง
ดังนั้นโดยทั่วไปแล้ว segment ตัวที่สองของ URL จึงเป็นการกำหนดว่าจะเรียกใช้งาน method ใด นั่นเอง
เราลองเพิ่มอีก method เข้าไป ดังนี้
<?php namespace App\Controllers; // กำนหด namespace คล้ายๆ กำหนด path ของไฟล์นี้ use CodeIgniter\Controller; // เรียกใช้งาน Controller class class Helloworld extends Controller // สร้าง Helloworld สืบทอดจาก Controller class { public function index() // กำหนด method ใน CI index() method จะเป็นค่าเริ่มต้น { echo 'Hello d World!'; // ทดสอบแสดงผล } public function comment() // เพิ่ม method ใหม่ { echo 'I am not flat!'; } }
เสร็จแล้วทดสอบเรียกใช้งานไปยัง URL ดังนี้
example.com/helloworld/comment/
ก็จะแสดงข้อความใหม่ตามที่เรากำหนด ขึ้นมาแทน
การส่งค่าจาก URI Segment ไปใช้งานใน Method
ในกรณีที่ URL มีมากกว่า 2 segment หรือ segment ตั้งแต่ตัว 3 เป็นต้นไป แต่ละค่าจะถูกส่งค่าเข้าไปยัง Method ในลักษณะ
method parameter ไปใช้งาน ดูตัวอย่าง URL ตัวอย่างต่อไปนี้
example.com/products/shoes/sandals/123
shoes() จะรับค่า parameter จาก URI segment ที่ 3 และ 4 (“sandals” and “123”)
ผ่านตัวแปร $sandals และ $id ตามลำดับ
<?php namespace App\Controllers; use CodeIgniter\Controller; class Products extends Controller { public function shoes($sandals, $id) { echo $sandals; echo $id; } }
อย่างไรก็ตาม เราสามารถจัดการส่วนของ segment ที่จะส่งมายัง method ว่าจะให้เป็น ส่วนใดๆ ก็ได้โดยการกำหนด rule ให้กับ
routes ตามรูปแบบการใช้งานในหัวข้อของบทความก่อนหน้านี้ http://niik.in/996 รวมถึงการกำหนด Default Method ด้วย
การ Remapping Method
ถึงแม้โดยทั่วไปแล้ว segment ตัวที่ 2 จะกำหนดให้เป็นการเรียกใช้ชื่อ method ที่จะใช้งาน แต่เราก็มีอีกวิธีที่สามารถกำหนดให้ ชื่อ
ที่แสดงใน URI Segment ที่สองเป็นคนละชื่อกับชื่อของ method ที่จะใช้งานได้ โดยวิธี Remapping หรือการจับคู่การทำงานของ method
ใหม่ในรูปแบบที่กำหนดเอง โดยสร้าง method ที่ชื่อ _remap()
public function _remap() { // ใส่โค้ดการทำงาน }
โดยที่เมื่อใดก็ตามที่เรากำหนด _remap() method เข้าไปใน Controller class มันจะทำงานอัตโนมัติ โดยไม่คำนึงถึงรูปแบบเดิมที่เรา
ได้กล่าวไป นั่นคือ ชื่อ method จะเป็นค่าใดๆ ก็จะเข้ามาทำงานใน method นี้ และทำงานตามเงื่อนไขหรือรูปแบบคำสั่งทีเราต้องการ หรือ
ก็คือเป็นการ override method นั่นเอง
ดูตัวอย่างการกำหนดด้านล่างประกอบ
<?php namespace App\Controllers; // กำนหด namespace คล้ายๆ กำหนด path ของไฟล์นี้ use CodeIgniter\Controller; // เรียกใช้งาน Controller class class Helloworld extends Controller // สร้าง Helloworld สืบทอดจาก Controller class { public function index() // กำหนด method ใน CI index() method จะเป็นค่าเริ่มต้น { echo 'Hello d World!'; // ทดสอบแสดงผล } public function comment() // เพิ่ม method ใหม่ { echo 'I am not flat!'; } public function ask() // เพิ่ม method ใหม่ { echo 'This is ask() method!'; } public function _remap($method) // กำหนดการ remapping method { if ($method === 'ask') { return $this->$method(); } else { return $this->index(); } } }
เมื่อเรากำหนด _remap() method ทำให้การเรียกไปยัง URL ที่มี segment ที่สองเป็นค่าใดๆ ก็ทำ ก็จะมาทำงานใน method นี้
นั่นคือ
example.com/helloworld example.com/helloworld/comment example.com/helloworld/ask example.com/helloworld/xxxx
ล้วนเรียกใช้งาน _remap() method โดยเมื่อเข้ามาทำงานใน method นี้แล้ว ก็จะมีเงื่อนไขว่า ให้ไปทำงาน index() method
ในทุกๆ Segment ที่สองที่เป็นค่าใดๆ ก็ตาม ยกเว้น ถ้าเป็นคำว่า ask ให้ทำงาน ask() method ดังนั้นในรูปแบบนี้ comment() method
จะไม่มีทางถูกเรียกใช้งาน แต่จะไปทำงานใน index() method แทน
เราสามารถกำหนด _remap() method กรณีต้องการส่งค่าเข้าไปใช้งานใน method ด้วยในรูปแบบดังนี้
// _remap(ชื่อ method, ...array ตัวแปร argument ทีส่งเข้าไปใน method) public function _remap($method, ...$params) { $method = 'process_'.$method; // กรณี method มีคำว่า process_ นำหน้า if (method_exists($this, $method)) // เช็คว่ามี method นี้ใน class หรือไม่ { return $this->$method(...$params); // ถ้ามี ส่ง parameter เข้าไปใช้งานใน method นั้นๆ พร้อมกับคือค่าการเรียกใช้งาน } // หรือกรณี error หรือไม่พบ throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound(); }
การกำหนด Private method
ในกรณีที่เราไม่ต้องการให้ method ใด ถูกเรียกใช้งาน ผ่าน URI segment เราสามารถกำหนดคำว่า protected เข้าไปแทนได้ดังนี้
protected function utility() { echo 'This is utility() method!'; }
method นี้จะไม่สามารถเรียกใช้งานผ่าน example.com/helloworld/utility/ ได้
การกำหนด Controller ในโฟลเดอร์ย่อย
เมื่อ app มีความซับซ้อนมากขึ้น จำเป็นที่เราควรจะสร้างโฟลเดอร์ย่อยสำหรับกำหนด Controller แต่ละส่วนแยกกันให้ชัดเจน และจัดการ
ได้ง่ายขึ้น โดยสามารถสร้างไว้ในโฟลเดอร์ app/Controllers/ โดยที่ชื่อโฟลเดอร์ย่อยที่สร้างจะต้องเป็นตัวพิมพ์ใหญ่เฉพาะอักษรตัวแรกเท่านั้น
ซึ่งถ้าเรากำหนดโฟลเดอร์ย่อยเพื่อใช้งาน จะทำให้ค่าปกติของ URI segment ตัวแรกจะต้องเป็นชื่อโฟลเดอร์นั้นๆ เว้นแต่เราไปปรับแต่งค่า
เพิ่มเติมในการกำหนด Routing
ตัวอย่างเช่น เราสร้างไฟล์ controller ที่ชื่อ Shoes.php ไว้ในโฟลเดอร์ย่อย Products
app/Controllers/Products/Shoes.php
การเรียกใช้งาน URL ก็จะเป็นในลักษณะคร่าวๆ ประมาณรูปแบบด้านล่าง
example.com/products/shoes/show/123
Property ที่มีใน Controller
ทุกครั้งที่เราสร้าง Controller class ใหม่ เราจำเป็นต้องทำการสืบทอดจาก CodeIgniter\Controller class เพื่อให้สามารถเรียกใช้งาน
property ต่างๆ ของ contrroller ได้ ซึ่งประกอบไปด้วยค่า ดังนี้
Request Object
คือ Request Instance เป็น class property ที่สามารถเรียกใช้งานผ่านคำสั่ง $this->request
Response Object
คือ Response Instance เป็น class property ที่สามารถเรียกใช้งานผ่านคำสั่ง $this->response
Logger Object
คือ Instance ของ Logger class เป็น class property ที่สามารถเรียกใช้งานผ่านคำสั่ง $this->logger
forceHTTPS
เป็น method ที่เราสามารถเรียกใช้งาน เพื่อบังคับให้ต้องเข้าใช้งานผ่าน HTTPS เท่านั้น รูปแบบการกำหนดเป็นเงื่อนไขการใช้งาน
จะเป็นดังนี้
if (! $this->request->isSecure()) { $this->forceHTTPS(); }
การกำหนด Helpers
เราสามารถกำหนด การเรียกใช้งาน Helper หรือตัวที่รวบรวมฟังก์ชั่นการจัดการบางอย่างเอาไว้ให้เราสามารถเรียกใช้งานได้สะดวก
เช่น ฟังก์ชั่นในการจัดการ array ฟังก์ชั่นในการจัดการ URL ฟังก์ชั่นในการจัดการ form เหล่านี้เป็นต้น
ใน CI4 ตัว URL Helper จะถูกเรียกโหลดใช้งานอัตโนมัติ เราสามารถเรียกใช้งานได้เลย โดยไม่ต้องโหลด ด้วยคำสัง เหมือน Helper อื่น
การโหลด helper ใน controller ใช้การกำหนดค่า ชื่อ helper ที่จะโหลดในรูปแบบ array แล้วกำหนดค่าให้กับ ตัวแปร $helpers ซึ่ง
เป้น property หนึ่งของ controller ดังนี้
<?php namespace App\Controllers; // กำนหด namespace คล้ายๆ กำหนด path ของไฟล์นี้ use CodeIgniter\Controller; // เรียกใช้งาน Controller class class Helloworld extends Controller // สร้าง Helloworld สืบทอดจาก Controller class { protected $helpers = ['array', 'form']; // โหลด array และ form helper มาใช้ใน controller นี้ public function index() // กำหนด method ใน CI index() method จะเป็นค่าเริ่มต้น { echo 'Hello d World!'; // ทดสอบแสดงผล echo site_url(); // ตัวอย่างการเรียกใช้งาน URL Helper } .................. ............... ........
การ Validating data
เป็นการตรวจสอบความถูกต้องของข้อมูล ใน Controller โดยเรียกใช้งานผ่านคำสั่ง validate() โดยกำหนด array ของ rule รูปแบบ
การตรวจสอบข้อมูลเป็นค่า parameter แรก และ parameter ที่สองสามารถกำหนดรูปแบบข้อความแจ้ง error เตือน กรณีข้อมูลไม่ผ่าน
เงื่อนไขการตรวจสอบที่เราสามารถกำหนดเองได้ โดยข้อมูลที่ใชืในการตรวจสอบ จะเรียกใช้งานผ่าน $this->request
ลองดูตัวอย่าง method ของ controller class ที่ใช้ตรวจสอบข้อมูลเบื้องต้นดังนี้
// ฟังก์ชั่นการอัพเดทข้อมูล user จาก $userID public function updateUser(int $userID) { // การตรวจสอบความถูกต้องของข้อมูล if (! $this->validate([ 'email' => "required|is_unique[users.email,id,{$userID}]", 'name' => 'required|alpha_numeric_spaces' ])) { // หากไม่ผ่านการตรวจสอบ ส่งไปหน้า Views?users/update โดยมีค่า error ส่งไปแสดงแจ้ง return view('users/update', [ 'errors' => $this->validator->getErrors() ]); } // กรณีผ่านการตรวจสอบ ทำคำสั่ง ต่อจากบรรทัดนี้ตามต้องการ }
เราสามารถกำหนดการเรียกใช้งาน $this->validate() ในส่วนของ model ได้ แต่บางครั้งก็เป็นสิ่งที่ง่ายและสะดวกในการกำหนด
และเรียกใช้งานผ่าน controller ขึ้นกับเราจะเลือกใช้แบบไหน
เกี่ยวกับการตรวจสอบความถูกต้องข้อมูล เราจะได้พูดถึงในรายละเอียดอีกครั้งภายหลัง
การใช้งาน Controller Filter
Controller Filter ใช้สำหรับ ทำหน้าที่บางอย่างก่อนหรือหลังการทำงานของ Controller เรียกใช้งานผ่านการกำหนดใน
rule ของ Routes ให้กับ URL ที่ต้องการ หรือกำหนดในไฟล์ app/Config/Filters.php อย่างใดอย่างหนึ่งก็ได้
โดย filter ที่ทำงานก่อน Controller จะทำหน้าที่หลักคือการแก้ไขหรือปรับปรุงข้อมูลของ Request object
ในขณะที่ filter ที่ทำงานหลังจาก Controller จะทำหน้าที่หลักในการปรับปรุงหรือก้ไข Response object
ตัวอย่างการใช้งาน Filter เช่น
- ป้องกัน CSRF attack ใน Request ที่ถูกส่งเข้ามา
- กำหนดเงื่อนไขหรือจำกัดการเข้าถึงการใช้งานบางส่วนตามกำหนด เช่น ส่วน admin
- จำกัดการเข้าถึง API endpoint เช่น ให้เรียก URL นี้ได้ไม่เกิน 1000 request ต่อวัน
- แสดงหน้าแจ้งการปรับปรุงเว็บไซต์ กรณีต้องการปิดการใช้งานชั่วคราวเพื่อปรับปรุงระบบ
- จัดการรูปแบบข้อมูลที่จะแสดงตามรูปแบบเงื่อนที่กำหนด
- และอื่นๆ
การสร้าง Filter
Filter เป็นรูปแบบ class อย่างง่าย ที่ทำการ implement จาก CodeIgniter\Filters\FilterInterface ประกอบด้วย
method สองตัวคือ before() และ after() โดยเมื่อเราสร้าง Filter จะต้องมีสอง method นี้เสมอ โดยอาจจะกำหนด
method ว่าง ไม่มีการทำงานใดๆ ก็ได้หาก ไม่ได้ใช้งาน method ในส่วนนั้น เช่น อาจจะใช้เฉพาะ before() method
ส่วน after() method กำหนดไว้โดยไม่ต้องมีโค้ดการทำงานด้านใน
เราจะมาลองสร้าง Filter อย่างง่าย เพื่อดูโครงสร้าง และรูปแบบการใช้งาน
ให้เราสร้างไฟล์ชื่อ MyFilter.php ไว้ในโฟลเดอร์ /App/Filters/MyFilter.php
/App/Filters/MyFilter.php
<?php namespace App\Filters; use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\HTTP\ResponseInterface; use CodeIgniter\Filters\FilterInterface; class MyFilter implements FilterInterface { public function before(RequestInterface $request, $arguments = null) { // จะเพียงแค่ทดสอบการสร้าง และเรียกใช้งานคร่าวๆ โดยให้เมื่อถูกเรียกใช้งาน // ให้เปลี่ยน URL ไปที่ /helloworld/comment return redirect()->to('/helloworld/comment'); } //-------------------------------------------------------------------- public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { // Do something here } }
เมื่อเรารู้ว่า Filter ใช้ทำอะไรได้บ้าง เราก็จะมาลองดูว่า Filter ทำงานอย่างไร โดยเริ่มต้นเราสร้างไฟล์ MyFilter.php
ตามโค้ดด้านบน โดยกำหนดการทำงานการ Controller ไว้ใน before() metthod ส่วน after() method ปล่อยว่างไปก่อน
การทำงานในส่วน before() ถ้ามองภาพอย่างง่าย ก็เช่น เวลาเมื่อผู้ใช้พยายามเข้าไปใช้งานหน้า admin เราก็ทำการดัก
หรือการตรวจสอบสิทธิ์การเข้าถึงหน้า admin ในส่วน ของ before() method นั่นเอง ซึ่งถ้าผ่านเงื่อนไขใน before() method
ไปได้ ก็จะไปทำในส่วนของ Controller ที่เรียกใช้งานต่อไป
ในที่นี้เราจำลองว่า ก่อนที่จะทำงานใน Controller เราบังคับให้เปลี่ยนไปยังหน้า URL /helloworld/comment เป็นคำสั่ง
redirect() อย่างงง่าย เพื่อจำลองการทำงานเท่านั้น
มาอธิบายแต่ละ method เพิ่มเติมเล็กน้อย ดังนี้
Before Filter
ในการกำหนดการทำงานใน before() method เราสามารถ ทำการ return ค่า $request objext ที่มีการปรับแต่งกลับ
เองมาใช้งานได้ ด้วยรูปแบบการทำงานที่ ส่วนของ before() method ถูกเรียกใช้และทำงานก่อนส่วนของ Controller เราก็
สามารถจะจัดการทิศทางการทำงานต่างๆ ได้ ไม่ว่าจะเปลี่ยนไปยังหน้าอื่น หรือกำหนดเงื่อนไขการเข้าใช้งาน อย่างระบบ
ตรวจสอบการล็อกอินเป็นต้น ดูตัวอย่างด้านล่าง
public function before(RequestInterface $request, $arguments = null) { $auth = service('auth'); if (! $auth->isLoggedIn()) { return redirect('login'); } }
โค้ดส่วนของการกำหนด before() method เพื่อตรวจสอบว่าถ้ายังไม่มีการล็อกอิน ให้ทำการ redirect ไปนังหน้า login
หากการทำงานในส่วนนี้ เป็นการ return ค่าเป็น Response instance เช่นการ โหลดหน้าเพจมาแสดง การทำงานก็จะเหมือน
ว่าสิ้นสุดลงในส่วนนี้ โดยไม่เข้าไปทำงานต่อในส่วนของ Controller ซึ่งกรณีการ redirect ก็เป็นรูปแบบหนึ่งของการ return
ค่าเป็น Response instance
After Filter
สำหรับ after() method จะทำงานหลังจากเรียกใช้งาน Controller แล้ว รูปแบบการทำงานก็คล้ายกับส่วนของ before()
แต่ใน after() จะคืนค่าเป็น $response object เป็นเหมือนส่วนที่ใช้กำหนด output สุดท้ายที่ต้องการแสดง เช่น ชนิดข้อมูล
ที่จะแสดงเป็น HTML หรือ Json ไฟล์ หรืออื่นๆ หรือใช้ตรวจสอบความถูกต้องและความปลอดภัยของ header หรือใช้สำหรับ
cache ข้อมูลที่จะแสดง หรือใช้สำหรับแก้ไขข้อความที่ไม่เหมาะสม เหล่านี้เป็นการทำงานในส่วนของ after() method
เมื่อเราสร้างไฟล์ MyFilter.php หรือสร้าง Filter class เรียบร้อยแล้ว เราจะยังไม่สามารถเรียกใช้งานได้ ต้องทำการกำหนด
ค่าในไฟล์ app/Config/Filters.php โดยประกอบด้วย property สี่ค่า ที่เราสามารถกำหนดการตั้งค่าได้ คือ
- $aliases
- $globals
- $methods
- $filters
$aliases
เป็นเหมือนที่สำหรับกำหนดชื่อเรียก หรือชื่อที่จะใช้งาน ให้กับ Filter class ที่เราสร้างหรือกำหนดขึ้นมา
เราเพิ่มตัวล่าสุดเข้าไปชื่อว่า myfilter เป็นชื่อที่เราจะใช้งาน โดย myfilter ให้ทำการใช้งาน Filter class ที่ชื่อ MyFilter
ค่าเริ่มต้น 3 ค่าที่มีอยู่ก่อนหน้า เป็นค่าที่มากับ CI4 อยู่แล้ว เราไม่ต้องทำอะไร หากต้องการกำหนด Filter เพิ่มเติม
ก็เพียงเพิ่ม ข้อมูล Filter ใหม่เข้าไปใน array ตามรูปแบบด้านล่าง ต่อไปเรื่อยๆ ตามต้องการ
public $aliases = [ 'csrf' => \CodeIgniter\Filters\CSRF::class, 'toolbar' => \CodeIgniter\Filters\DebugToolbar::class, 'honeypot' => \CodeIgniter\Filters\Honeypot::class, 'myfilter' => \App\Filters\MyFilter::class, ];
เราสามารถกำหนด ชื่อ ให้กับ Filter หลายๆ อันรวมกันได้ ในรูปแบบดังนี้
public $aliases = [ 'apiPrep' => [ \App\Filters\Negotiate::class, \App\Filters\ApiAuth::class ] ];
เมื่อเรากำหนดในส่วนของ $aliases property เริ่มร้อยแล้ว Filter ของเราก็พร้อมใช้งาน เราอาจจะไปกำหนด
การเรียกใช้ในส่วนของการใช้งาน Routes โดยเพิ่มเข้าไปใน Option ในลักษณะดังนี้
app/config/Routes.php
$routes->get('/helloworld/ask', 'Helloworld::ask', ['filter' => 'myfilter']); // http://niik.in/996
หรือถ้าเราไม่ต้องการไปกำหนดการเเรียกใช้งานใน Routes เราก็สามารถกำหนดในไฟล์ Filter.php นี้ได้ ซึ่งจะอธิบาย
ใว้ใน property ที่เหลือ ตามด้านล่าง
$globals
เป็นการกำหนดการเรียกใช้งาน Filter โดยจะถูกใช้งานกับทุกๆ Request หรือก็คือ ไม่ว่าจะเข้า URL ใดๆ ก็ตาม ก็จะ
ต้องทำงานหรือใช้งาน Filter ที่กำหนดในส่วนนี้ ดังนั้น เราจะต้องระมัดระวังในการกำหนดการเรียกใช้ Filter ในส่วนนี้
เพราะหากเป็น Filter ที่ไม่ได้จำเป็นสำหรับทุกหน้า แต่กลับต้องถูกเรียกใช้งานโดยไม่จำเป็น ก็ทำให้โปรแกรมทำงานช้าได้
public $globals = [ 'before' => [ //'honeypot' // 'csrf', 'myfilter', ], 'after' => [ 'toolbar', //'honeypot' ], ];
อันนี้สมมติให้ดูการกำหนดการเรียกใช้ ค่าเริ่มต้นใน CI4 กำหนดไว้เฉพาะ after() method ที่ใช้ toobar Filter ซึ่งเป็นส่วน
ที่ใช้ใน Debug เราสามารถ comment ปิดได้หากนำขึ้น server ในตัวอย่างเราเพิ่ม myfiller ซึ่งเป็น Filter ที่เราจะใช้ ไว้เฉพาะ
before() method ซึ่งสมมติเท่านั้น แต่ถ้าหากกำหนดจริง ก็จะเกิด error ขึ้น เพราะว่า myfilter ของเราทำการ redirect()
จากหน้าหนึ่งไปยังอีกหน้าเฉยๆ ดังนั้น ถ้าเรียกใช้งานจริง ก็จะเป็นการวนลูปไม่จบสิ้น
แต่ในการกำหนดส่วนของ $globals property ก็จะมีประโยชน์ในกรณีที่ ใช้สำหรับ Filter ที่จำเป็นที่กำหนดให้กับทุก
Request จริงๆ และยังสามารถ ยกเว้นบาง URL ที่ไม่ต้องการให้ Filter ที่กำหนดใช้งานได้ โดยเพิ่ม key ที่ชื่อ except แล้ว
กำหนด URL ที่ต้องการยกเว้นเข้าไป โดยกำหนดได้ทั้ง URL ปกติ หรือแบบ Regex หรือกำหนดหลาย URL เป็น array ได้
ตัวอย่างการกำหนด ดังตัวอย่างด้านล่าง
// กำหนดแบบ csrf Filter ไม่ต้องใช้งานในหน้า api/ ทั้งหมด public $globals = [ 'before' => [ 'csrf' => ['except' => 'api/*'] ], 'after' => [] ];
// แบบกำหนด หลาย URL ใช้แบบ array public $globals = [ 'before' => [ 'csrf' => ['except' => ['foo/*', 'bar/*']] ], 'after' => [] ];
$methods
เป็นส่วนของการกำหนดการเรียกใช้งาน Filter ให้กับ Request Method เฉพาะที่เราต้องการเรียกใช้ โดยสามารถกำหนด
array ของ Filter ที่ต้องการไปใน key ของ method ที่จะใช้ ในลักษณะดังนี้
public $methods = [ 'post' => ['foo', 'bar'], 'get' => ['myfilter'] ]
ตัวอย่างข้างต้น เรากำหนดให้ใช้งาน Filter ชื่อว่า myfilter ทุกๆ Request mehod ที่เป็น GET
โดยการกำหนดการเรียกใช้งานผ่าน $methods property นี้ ตัว Filter จะทำงานได้เฉพาะในส่วนของ before() mehod
$filters
การเรียกใช้งานผ่านการกำหนดค่า Filter ใน $filter property เป็นอีกวิธีในการกำหนดการเรียกใช้งาน Filter โดยสามารถ
ระบุการเรียกใช้งานได้ทั้ง before() และ after() method โดยกำหนด array ของ URL ที่จะใช้งาน สมมติเรราเรียกใช้งาน
myfilter ก็จะกำหนดดังนี้
public $filters = [ 'myfilter' => ['before' => ['helloworld/ask*']], ];
หรือตัวอย่างการกำหนดเพิ่มเติม ก็จะเป็นดังนี้
public filters = [ 'foo' => ['before' => ['admin/*'], 'after' => ['users/*']], 'bar' => ['before' => ['api/*', 'admin/*']] ];
ตัวอย่างด้านบน "foo" Filter ถูกกำหนดให้เรียกใช้งาน before() method ใน URL admin/*
และใช้งาน after() method ใน URL users/*
ใน ขณะที่ "bar" Filter ถูกกำหนดให้ใช้งานเฉพาะ before() method โดยใช้งานกับ URL api/* กับ admin/*
การกำหนด Filter arguments
กรณีที่เราต้องการส่งค่าไปใช้งานใน Filter หรือการกำหนด Filter argument เราจะต้องทำผ่าน การกำหนด Option
ใน Routes สมมติเช่น myfilter Filter ของเรา จะให้ส่งคำว่าง comment เข้าไปใน เพื่อเรียกใช้งาน
public function before(RequestInterface $request, $arguments = null) { return redirect()->to('/helloworld/'.$arguments[0]); }
โดยค่า argument ที่ส่งเข้ามาใน before() method จะต้องเป็น array เราต้องการเอา array ค่าแรกมาต่อเป็น URL
ที่ต้องการ redirect ไปตามตัวอย่างการกำหนดด้านบน
เวลาเรียกใช้งาน โดยกำหนดในส่วนของ Routes.php ก็จะประมาณนี้
$routes->get('/helloworld/ask', 'Helloworld::ask', ['filter' => 'myfilter:comment']);
เมื่อเปิด URL /hellowrold/ask ก็จะใช้งาน 'myfilter' Filter โดยส่ง array เท่ากับ ['comment'] เข้าไปใน before()
method ถ้ามีหลายค่าก็คั่นด้วย , เช่น
$routes->get('/helloworld/ask', 'Helloworld::ask', ['filter' => 'myfilter:comment,utility']);
ก็จะเป็นการส่งค่า ['comment','utility'] เป็น argument เข้าไป เวลาเรียกใช้ค่าที่ส่งเข้ามาใน before() method ก็อ้างอิง
ตัวแปร $arguments[0] โดยระบุ key ของ array ที่จะใช้งาน
เนื้อหาเกี่ยวกับ Controller และ Controller Filter ซึ่งเป็นหัวหาหลักก็จะประมาณนี้ ยังมีปลีกย่อยอืนๆ เกี่ยวกับ Controller
จะได้นำมาเพิ่มติมในบทความต่อๆ ไป