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 fileapp/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:
- Đăng ký middleware vào mảng
routeMiddleware
trongapp/Http/Kernel.php
- 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 quaApp\Providers\RouteServiceProvider
tương ứng với các routeweb
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 methodterminate
trên 1 instance mới, nếu bạn muốn gọi methodhandle
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 methodsingleton
trongAppServiceProvider
use App\Http\Middleware\TerminatingMiddleware;
/**
* Register any application services.
*
* @return void
*/
public function register()
{
$this->app->singleton(TerminatingMiddleware::class);
}
All rights reserved