Get in touch
or send us a question?
CONTACT

Laravel Middleware

Defining Middleware

  • Tạo middleware thông qua command line:
php artisan make:middleware EnsureTokenIsValid

Middleware & Responses

  • Chúng ta có thể định nghĩa before Middleware để xử lý các logic trước khi check Middleware
<?php
 
namespace App\Http\Middleware;
 
use Closure;
 
class BeforeMiddleware
{
    public function handle($request, Closure $next)
    {
        // Perform action
 
        return $next($request);
    }
}
  • Hoặc after Middleware
<?php
 
namespace App\Http\Middleware;
 
use Closure;
 
class AfterMiddleware
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);
 
        // Perform action
 
        return $response;
    }
}

Registering Middleware

  • Middleware có 2 loại: Global và local middleware

Global Middleware

  • Nếu muốn đăng ký 1 global middleware thì bạn chỉ cần thêm middleware vào mảng $middleware trong file app/Http/Kernel.php
protected $middleware = [
        // \App\Http\Middleware\TrustHosts::class,
        \App\Http\Middleware\TrustProxies::class,
        \Illuminate\Http\Middleware\HandleCors::class,
        \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    ];

Assigning Middleware To Routes

  • Đăng ký route middleware bạn cần 2 bước:
  1. Đăng ký middleware vào mảng routeMiddleware trong app/Http/Kernel.php
  2. Sử dụng tại route
// Within App\Http\Kernel class...
 
protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
    'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
    'can' => \Illuminate\Auth\Middleware\Authorize::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
Route::get('/profile', function () {
    //
})->middleware('auth');
  • Có thể thêm nhiều middleware cho cùng 1 route
Route::get('/', function () {
    //
})->middleware(['first', 'second']);
  • Hoặc có thể dùng tên class của middleware để đăng ký:
use App\Http\Middleware\EnsureTokenIsValid;
 
Route::get('/profile', function () {
    //
})->middleware(EnsureTokenIsValid::class);

Excluding Middleware

  • Khi đăng ký middleware group route, đôi khi bạn cần loại bỏ middleware cho 1 route nào đó thì có thể sử dụng method withoutMiddleware
use App\Http\Middleware\EnsureTokenIsValid;
 
Route::middleware([EnsureTokenIsValid::class])->group(function () {
    Route::get('/', function () {
        //
    });
 
    Route::get('/profile', function () {
        //
    })->withoutMiddleware([EnsureTokenIsValid::class]);
});
  • Hoặc bạn cũng có thể loại bỏ middleware theo group route:
use App\Http\Middleware\EnsureTokenIsValid;
 
Route::withoutMiddleware([EnsureTokenIsValid::class])->group(function () {
    Route::get('/profile', function () {
        //
    });
});
  • withoutMiddleware chỉ có thể loại bỏ route middleware không thể loại bỏ global middleware

Middleware Groups

  • Đôi khi bạn muốn nhóm nhiều middleware thành group để dễ dàng sử dụng cho các route, bạn có thể thêm các group trong mảng $middlewareGroups trong file HTTP kernel.
  • Mặc định laravel có 2 group middleware là web và api, 2 middleware group này sẽ tự động được áp dụng vào ứng dụng của bạn thông qua App\Providers\RouteServiceProvider tương ứng với các route web và api:
/**
 * 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,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],
 
    'api' => [
        'throttle:api',
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],
];
  • Middleware group cũng có thể được gán cho các route bằng cách sử dụng cú pháp giống như các middware riêng lẻ khác:
Route::get('/', function () {
    //
})->middleware('web');
 
Route::middleware(['web'])->group(function () {
    //
});

Sorting Middleware

  • Hiếm khi, bạn muốn middleware thực thi theo 1 thứ tự nhất định thì bạn nên kiểm soát chúng trong mảng thuộc tính $middlewarePriority:
/**
 * The priority-sorted list of middleware.
 *
 * This forces non-global middleware to always be in the given order.
 *
 * @var string[]
 */
protected $middlewarePriority = [
    \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class,
    \Illuminate\Cookie\Middleware\EncryptCookies::class,
    \Illuminate\Session\Middleware\StartSession::class,
    \Illuminate\View\Middleware\ShareErrorsFromSession::class,
    \Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests::class,
    \Illuminate\Routing\Middleware\ThrottleRequests::class,
    \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class,
    \Illuminate\Contracts\Session\Middleware\AuthenticatesSessions::class,
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
    \Illuminate\Auth\Middleware\Authorize::class,
];

Middleware Parameters

  • Middleware cũng có thể nhận tham số vào để xử lý, các tham số dduwwocj truyền vào middleware đứng sau tham số $next:
<?php
 
namespace App\Http\Middleware;
 
use Closure;
 
class EnsureUserHasRole
{
    /**
     * Handle the incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string  $role
     * @return mixed
     */
    public function handle($request, Closure $next, $role)
    {
        if (! $request->user()->hasRole($role)) {
            // Redirect...
        }
 
        return $next($request);
    }
 
}
  • Truyền tahm số ở route:
Route::put('/post/{id}', function ($id) {
    //
})->middleware('role:editor');

Terminable Middleware

  • Trong trường hợp các bạn cần xử lý logic sau khi HTTP response đã được gửi đến trình duyệt, bạn có thể dùng method terminate trong class Middleware:
  • Method terminate có 2 tham số $request và $response
<?php
 
namespace Illuminate\Session\Middleware;
 
use Closure;
 
class TerminatingMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        return $next($request);
    }
 
    /**
     * Handle tasks after the response has been sent to the browser.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Illuminate\Http\Response  $response
     * @return void
     */
    public function terminate($request, $response)
    {
        // ...
    }
}
  • Khi method terminate được gọi, Laravel sẽ xóa instance cũ của middleware và xử lý logic trong method terminate trên 1 instance mới, nếu bạn muốn gọi method handle và terminate trên cùng 1 phiên bản instance thì bạn cần đăng ký middleware với service container bằng method singleton trong AppServiceProvider
use App\Http\Middleware\TerminatingMiddleware;
 
/**
 * Register any application services.
 *
 * @return void
 */
public function register()
{
    $this->app->singleton(TerminatingMiddleware::class);
}