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:
php artisan make:middleware EnsureTokenIsValidLệ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ủ:
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:
class BeforeMiddleware
{
public function handle(Request $request, Closure $next): Response
{
// perform action
return $next($request);
}
}Để thực thi sau khi đã pass request:
$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:
Route::get()->middleware(Authenticate::class);Gán nhiều middleware:
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:
protected $middlewareAliases = [
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsValid::class,
];Khi đã define alias bạn có thể sử dụng nó để gán trong route:
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:
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:
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à web và api, 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 web và api tương ứng:
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:
Route::get()->middleware('web');
Route::middleware(['web'])->group(function() {
// ...
});Lưu ý: middleware group web và api được tự động apply cho routes/web.php và routes/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:
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
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:
Route::put()->middleware('role:editor');