Laravel – Middleware

Middleware đóng vai trò trung gian giữa requestresponse. Nó như 1 dạng cơ chế lọc. Ví dụ Laravel có một middleware để xác định người dùng đã đăng nhập chưa, nếu đăng nhập, sẽ được chuyển đến trang home, còn chưa thì chuyển đến trang login.

Định nghĩa một middleware

có thể dùng lệnh command

php artisan make:middleware <middleware-name>

Thay <middleware-name> bằng tên middleware của bạn, bạn có thể xem middleware vừa tạo trong thư mục app/Http/Middleware

ví dụ

Step 1 : Thực thi lệnh command bên dưới để tạo 1 middleware AgeMiddleware.

php artisan make:middleware AgeMiddleware

Khi tạo thành công, bạn sẽ có kết quả như hình bên dưới.

Step 2 : middleware AgeMiddleware sẽ được tạo ra trong thư mục app/Http/Middleware, mở file này bạn sẽ có nội dung như sau:

<?php
###
namespace App\Http\Middleware;
###
use Closure;
###
class AgeMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        return $next($request);
    }
}

Đăng ký middleware

Sau khi tạo, cần đăng ký middleware trước khi sử dụng. Việc đăng ký thực hiện trong file app/Http/Kernel.php. Có các cách đăng ký Middleware sau:

Global Middleware

middleware sẽ chạy khi với mỗi HTTP request tới hệ thống. Bạn có thể thêm class để đăng ký trong $middleware

protected $middleware = [
    \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
    \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
    \App\Http\Middleware\TrimStrings::class,
    \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    \App\Http\Middleware\TrustProxies::class,
];

Route Middleware

Để đăng ký Route Middleware, trước tiên thêm keyvalue vào thuộc tính $routeMiddleware

protected $routeMiddleware = [
    'auth' => \Illuminate\Auth\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,
];

sau đó dùng key này gắn cho 1 route nào đó

Route::get('admin/profile', function () {
    //
})->middleware('auth');

middleware Groups

Hoặc nhóm các Middleware thành từng nhóm với 1 key

protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        // \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],
###
    'api' => [
        'throttle:60,1',
        'bindings',
    ],
];

Và dùng key này gán cho route

Route::get('/', function () {
    //
})->middleware('web');
###
Route::group(['middleware' => ['web']], function () {
    //
});

Middleware Tham số

Bạn có thể truyền vào tham số cho Middleware. Ví dụ nếu chương trình cần phân biệt các user có role khác nhau user, admin, super admin… Điều này có thể thực hiện thông qua việc truyền tham số vào Middleware. tham số được truyền sau tham số $next của handle.

public function handle($request, Closure $next)
{
    echo "Executing statements of handle method of TerminateMiddleware.";
    return $next($request);
}

Ví dụ

Step 1 : Tạo middleware RoleMiddleware bằng lệnh command.

php artisan make:middleware RoleMiddleware

Step 2 : Thêm code như bên dưới vào phương thức handle của file vừa tạo.
app/Http/Middleware/RoleMiddleware.php

<?php
###
namespace App\Http\Middleware;
###
use Closure;
###
class RoleMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next, $role)
    {
        echo "Role: ".$role;
        return $next($request);
    }
}

Step 3 : Đăng ký RoleMiddleware trong file app\Http\Kernel.php vào Route Middleware như hình

Step 4 : Tạo TestController với lệnh command sau:

php artisan make:controller TestController

Step 5 : Thêm code sau vào app/Http/TestController.php.

<?php
###
namespace App\Http\Controllers;
######
use Illuminate\Http\Request;
###
class TestController extends Controller
{
    public function index(){
        echo "<br>Test Controller.";
    }
}

Step 6 : Thêm route sau vào file app/Http/routes.php.

Route::get('role',[
   'middleware' => 'Role:editor',
   'uses' => 'TestController@index',
]);

Step 7 : Vào trang http://localhost/laravel/role kiểm tra kết quả.

Terminable Middleware

Terminable middleware thực hiện một công việc sau khi HTTP response đã gửi đến trình duyệt người dùng.

Terminable middleware sẽ nhận cả 2 tham số $request$response.

Ví dụ

Step 1 : Tao TerminateMiddleware bằng lệnh command dưới đây:

php artisan make:middleware TerminateMiddleware

Kết quả khi chạy thành công

Step 2 : Thêm code sau vào file TerminateMiddleware mới tạo.

app/Http/Middleware/TerminateMiddleware.php

<?php
#########
namespace App\Http\Middleware;
######
use Closure;
###
class TerminateMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        echo "Executing statements of handle method of TerminateMiddleware.";
        return $next($request);
    }
###
    public function terminate($request, $response){
        echo "<br>Executing statements of terminate method of TerminateMiddleware.";
    }
}

Step 3 : Đăng ký TerminateMiddleware trong file app\Http\Kernel.php.

Step 4 : Tạo ABCController bằng dòng lệnh command bên dưới:

php artisan make:controller ABCController

Step 5 : Thêm code như bên dưới vào ABCController mới tạo.

app/Http/ABCController.php

<?php
###
namespace App\Http\Controllers;
###
use Illuminate\Http\Request;
###
class ABCController extends Controller
{
    public function index(){
        echo "<br>ABC Controller.";
    }
}

Step 6 : Thêm route bên dưới vào file route/web.php.

Route::get('terminate',[
   'middleware' => 'terminate',
   'uses' => 'ABCController@index',
]);

Step 7 : Vào http://localhost/laravel/terminate để xem kết quả