Laravel5 : รู้จักกับ Middleware
บทความนี้เป็นเป็นเรื่องของสิ่งที่เรียกว่า Middleware บน Laravel 5 ที่กว่าจะเข้าใจก็เล่นงงไปนานเลย แต่ความจริงแล้วมันก็ไม่ได้ซับซ้อนอะไร เลยอยากจะเขียนแชร์ไว้ เผื่อเป็นประโยชน์ และเผื่อผมลืมก็จะได้กลับมาอ่านด้วย
บทความนี้อ้างอิงกับ Laravel 5.2
Middleware คืออะไร
Middleware คือ กลไกสำหรับคัดกรอง request ที่เข้ามาภายในแอปของเรา โดยแอปของเราสามารถมี middleware ได้หลายตัว แต่ละตัวก็มีหลักการทำงานแตกต่างกันไป เช่น ถ้าจะเข้า url นี้ต้องล็อคอินแล้ว หรือเป็น Admin เท่านั้น เป็นต้น
สามารถอ่านรายละเอียดทั้งหมดได้ที่ document ของ Laravel
https://laravel.com/docs/5.1/middleware
การทำงาน
หลังจากที่ผู้ใช้เรียก route ก็จะมีการเช็ค Middleware ต่างๆ ที่ต้องตรวจสอบ เช่น จำเป็นต้องผ่าน Middleware ชื่อ Auth เพราะจำเป็นต้องล็อคอินก่อน ถ้ายังไม่ได้ล็อคอินก็จะไม่สามารถผ่านไปได้ ก็จะต้อง redirect ไปหน้าล็อคอินก่อน เป็นต้น
ภายใน class ของ middleware จะมี Method ชื่อว่า handle ที่จะระบุว่าให้ทำงานอย่างไร ตัวอย่างโค้ดข้่างล่างนี้ คือ middleware ของ Authenticate
public function handle($request, Closure $next) { if ($this->auth->guest()) { if ($request->ajax()) { return response('Unauthorized.', 401); } else { return redirect()->guest('auth/login'); } } return $next($request); }
หลักๆ คือการตรวจสอบว่าเป็น guest (ยังไม่ได้ล็อคอิน) หรือไม่ ถ้าเป็นก็ให้เด้งไปหน้าล็อคอิน หรือถ้าล็อคอินอยู่แล้วก็ส่งต่อไปยัง middleware ตัวถัดไป (next request)
return $next($request);
ไฟล์ของ Middleware
ให้เข้าไปที่ app/Http/Middleware ไฟล์ต่างๆจะสถิตที่อยู่นี่ จะเห็นว่ามี middleware ที่ laravel เตรียมมาให้ด้วย เช่น Authenticate , VerifyCsrfToken หากเราจะสร้างขึ้นเอง ก็สามารถสร้างได้ที่นี่
การสร้าง Middleware
สามารถสร้างไฟล์ .php โดยการ copy ไฟล์ หรือลอกโค้ด middleware ตัวอื่นๆ แล้วเปลี่ยนชื่อคลาส ก็ทำได้เช่นกัน (ผมก็ชอบทำ)
แต่วิธีที่ถูกต้องคือ การใช้ command line
$ php artisan make:middleware MyMiddleware
MyMiddleware คือ ชื่อคลาสที่ต้องการ
จากนั้นไฟล์ middleware จะถูกสร้างขึ้น พร้อม handle แล้วละ
การกำหนดให้ Middleware ทำงาน
หลังจากที่เราสร้าง middleware แล้ว มันจะยังไม่ถูกเรียกใช้งาน เราจะต้องกำหนดมันให้แอปของเรารู้จักก่อน (Registering)
วิธีการคือ ไปที่ app/Http/kernel.php
ภายในจะมีพบว่ามีตัวแปร Array
ถ้าเป็น laravel 5.0 จะมีแค่ 2 ตัว แต่ถ้าเป็น 5.2 จะมี 3 ตัว
$middleware (ไม่มีใน laravel 5.0)
คือ array ที่เก็บ middleware ที่ ทุก request ที่เข้ามา จะต้องผ่านทุก middleware ในนี้ถึงจะผ่านไปได้
$middlewareGroups
คือ สามารถแยก middleware เป็นกลุ่มๆ request ที่จะผ่านไปได้ จะต้องผ่านทุก middleware ในกลุ่ม เช่น กลุ่ม API mobile , API web เป็นต้น
$routeMiddleware
คือ middleware สำหรับ route โดยการจะใช้งาน middleware ในนี้จะต้องไปกำหนดที่ route ด้วย เช่น
กำหนดว่า admin/profile ต้องผ่าน middleware ชื่อ Auth
Route::get('admin/profile', ['middleware' => 'auth', function () { // do something. }]);
หรือ กำหนดหลายๆ middleware ใน route เดียว
Route::get('/', ['middleware' => ['first', 'second'], function () { // do something. }]);
หรือ สามารถเขียนแบบนี้ก็ได้
Route::get('/', function () { // do something. })->middleware(['first', 'second']);
สามารถใส่ parameter ให้ middleware ได้ด้วย เช่น
Route::get('/', ['middleware' => 'mode:editor', function ($id) { // }]);
ในที่นี้ Middleware mode มีการส่งค่า editor ให้ handle
แล้วที่ handle ของ middleware Closure จะมี argument เพิ่มขึ้นมา ตัวนึง
public function handle($request, Closure $next, $mode) { // ... }
ตัวอย่าง
kernel.php
<?php namespace App\Http; use Illuminate\Foundation\Http\Kernel as HttpKernel; class Kernel extends HttpKernel { /** * The application's global HTTP middleware stack. * * These middleware are run during every request to your application. * * @var array */ protected $middleware = [ \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class, \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, ]; /** * The application's route middleware groups. * * @var array */ protected $middlewareGroups = [ 'web' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, ], 'api' => [ 'throttle:60,1', ], ]; /** * The application's route middleware. * * These middleware may be assigned to groups or used individually. * * @var array */ protected $routeMiddleware = [ 'auth' => \App\Http\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, ]; }
กำหนด Middleware ผ่าน Constructor ของ Controller
ที่ Controller ก็สามารถกำหนด middleware ได้เช่นกัน โดยสามารถกำหนดได้ที่ constructor ได้เลย
public function __construct() { $this->middleware('auth'); }
สรุป
เรื่อง middleware เป็นเรื่องสำคัญเรื่องหนึ่งที่ต้องรู้เลย ของ Laravel และจริงๆแล้วก็ไม่ได้เป็นเรื่องที่ซับซ้อนอะไรมากนัก หากเข้าใจแล้วจะสามารถนำไปใช้แอปของเราก็จะมีประสิทธิภาพมากขึ้น
(: