web analytics

Laravel5 : รู้จักกับ Middleware

cover

บทความนี้เป็นเป็นเรื่องของสิ่งที่เรียกว่า 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 หากเราจะสร้างขึ้นเอง ก็สามารถสร้างได้ที่นี่

1

 

การสร้าง Middleware

สามารถสร้างไฟล์ .php โดยการ copy ไฟล์ หรือลอกโค้ด middleware ตัวอื่นๆ แล้วเปลี่ยนชื่อคลาส ก็ทำได้เช่นกัน (ผมก็ชอบทำ)
แต่วิธีที่ถูกต้องคือ การใช้ command line

      $ php artisan make:middleware MyMiddleware

MyMiddleware คือ ชื่อคลาสที่ต้องการ

จากนั้นไฟล์ middleware จะถูกสร้างขึ้น พร้อม handle แล้วละ

2-1

 

การกำหนดให้ Middleware ทำงาน

หลังจากที่เราสร้าง middleware แล้ว มันจะยังไม่ถูกเรียกใช้งาน เราจะต้องกำหนดมันให้แอปของเรารู้จักก่อน (Registering)

วิธีการคือ ไปที่ app/Http/kernel.php

3

 

ภายในจะมีพบว่ามีตัวแปร 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 และจริงๆแล้วก็ไม่ได้เป็นเรื่องที่ซับซ้อนอะไรมากนัก หากเข้าใจแล้วจะสามารถนำไปใช้แอปของเราก็จะมีประสิทธิภาพมากขึ้น

(: