Học Laravel – Bài 12: Middleware

Giới thiệu Middleware trong Laravel:

Middleware giúp kiểm tra và lọc http request. Ví dụ, Laravel có 1 middleware để xác thực user. Nếu user chưa đăng nhập, middleware sẽ redirect đến trang login. Nếu đã đăng nhập, middleware cho phép request đi tiếp sâu hơn vào ứng dụng.

Middleware có thể thực hiện nhiều tác vụ ngoài xác thực. Ví dụ logging middleware để log tất cả request vào. Nhiều middleware trong Laravel, bao gồm xác thực và CSRF. Các middleware này nằm ở thư mục app/Http/Middleware.

Define middleware:

Dùng lệnh Artisan:

ShellScript
php artisan make:middleware EnsureTokenIsValid

Lệnh này tạo 1 class EnsureTokenIsValid trong thư mục app/Http/Middleware. Trong middleware này chúng ta chỉ cho phép tiếp cận tới những route nếu token khớp với giá trị được chỉ định. Nếu không, redirect đến trang chủ:

PHP
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class EnsureTokenIsValid
{
    public function handle(Request $request, Closure $next): Response
    {
        if ($request->input('token') !== 'my-scret-token') {
            return redirect('home');
        }
        
        return $next($request);
    }
}

Ở ví dụ trên, nếu token không khớp với chuỗi, middleware sẽ trả về 1 http redirect, còn ngược lại request sẽ được pass qua. Để pass request, gọi $next callback với tham số $request.

Tất cả middleware được resolve thông qua service container, vì vậy bạn có thể type-hint bất kỳ phụ thuộc nào bạn muốn ở middleware constructor.

Middleware & Response:

Middleware cũng có thể thực thi task trước hoặc sau khi request pass. Ví dụ để thực thi task trước khi pass request đi:

PHP
class BeforeMiddleware
{
    public function handle(Request $request, Closure $next): Response
    {
        // perform action
        
        return $next($request);
    }
}

Để thực thi sau khi đã pass request:

PHP
$response = $next($request);
// perform action

return $response;

Đăng ký Middleware:

Global middleware:

Nếu bạn muốn middleware chạy trong mỗi HTTP request, liệt kê middleware trong thuộc tính $middleware trong class app/Http/Kernel.php.

Gán Middleware cho Route:

Gọi method middleware khi define route:

PHP
Route::get()->middleware(Authenticate::class);

Gán nhiều middleware:

PHP
Route::get()->middleware([First::class, Second::class]);

Để thuận tiện, bạn có thể gán alias cho middleware trong file Kernel.php. Thuộc tính $middlewareAliases chứa các middleware có sẵn trong Laravel. Bạn có thể thêm middleware của bạn vào list này và gán cho nó alias:

PHP
protected $middlewareAliases = [
    'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsValid::class,
];

Khi đã define alias bạn có thể sử dụng nó để gán trong route:

PHP
Route::get()->middleware('verified');

Loại trừ Middleware:

Khi gán middleware cho group, bạn có thể loại trừ cho 1 số route trong group đó sử dụng method withoutMiddleware:

PHP
Route::middleware([EnsureTokenIsValid::class])->group(function() {
    Route::get('/profile')->withoutMiddleware([EnsureTokenIsValid::class]);
});

Bạn cũng có thể exclude 1 nhóm middleware cho 1 group route:

PHP
Route::withoutMiddleware([EnsureTokenIsValid::class])->group(function() {
    Route::get('/abc', ...);
});

Middleware Group:

Sử dụng thuộc tính $middlewareGroups trong HTTP kernel.

Laravel có sẵn 2 group middleware là webapi, chứa nhiều middleware thông dụng. Những middleware group này tự động apply bởi service provider App\Providers\RouteServiceProvider đến route trong file route webapi tương ứng:

PHP
protected $middlewareGroups = [
    'web' => [
        ...\EncryptCookies::class,
        ...\VerifyCsrfToken::class,
        ...
    ],
    'api' => []
];

Middleware group có thể được gán cho route và controller action sử dụng cùng cấu trúc như middleware:

PHP
Route::get()->middleware('web');

Route::middleware(['web'])->group(function() {
    // ...
});

Lưu ý: middleware group webapi được tự động apply cho routes/web.phproutes/api.php bởi App\Providers\RouteServiceProvider.

Sắp xếp Middleware:

Sử dụng thuộc tính $middlewarePriority trong file Kernel.php. Khai báo thuộc tính này trong file:

PHP
protected $middlewarePriority = [
    ...
];

Tham số cho Middleware:

Middleware có thể nhận thêm tham số. Ví dụ bạn muốn verify user role, bạn có thể tạo 1 EnsureUserHasRole middleware nhận role làm tham số. Các tham số bổ sung được đặt sau tham số $next:

PHP
<?php
 
namespace App\Http\Middleware;
 
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
 
class EnsureUserHasRole
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next, string $role): Response
    {
        if (! $request->user()->hasRole($role)) {
            // Redirect...
        }
 
        return $next($request);
    }
 
}

Các tham số của middleware được chỉ định khi define route bởi dấu : ngăn giữa tên middleware và tham số. Nhiều tham số có thể ngăn cách bởi dấu phẩy:

PHP
Route::put()->middleware('role:editor');

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *