-5

Middleware trong laravel

Giới thiệu

Middleware cung cấp một giải pháp khá tiện ích cho việc filtering HTTP các requests vào ứng dụng. Ví dụ, Laravel có chứa một middleware xác thực người dùng đăng nhập vào hệ thống. Nếu user chưa đăng nhập, middleware sẽ chuyển hướng user tới màn hình đăng nhập. Tuy nhiên, nếu user đã đăng nhập rồi, thì middleware sẽ cho phép request được thực hiện tiếp tiến trình xử lý vào ứng dụng.

Tất nhiên, bạn có thể viết thêm middleware để thực hiện nhiều tác vụ nữa ngoài kiểm tra đăng nhập vào hệ thống. Một CORS middleware có trách nhiệm cho việc thêm các header hợp lý vào trong tất cả các response gửi ra ngoài. Một logging middleware có thể ghi log cho tất cả các request tới ứng dụng.

Có vài middleware đã có sẵn trong Laravel framework, bao gồm middlware xác thực, CSRF protection. Tất cả được nằm trong thư mục app/Http/Middleware.

Tạo Middleware

Để tạo mới một middleware, sử dụng lệnh make:middleware:

php artisan make:middleware CheckAge

Câu lệnh này sẽ tạo ra class CheckAge bên trong thư mục app/Http/Middleware. Trong middleware này, chúng ta chỉ cho phép truy cập vào route nếu giá trị age lớn hơn 200. Ngược lại, chúng ta sẽ chuyển hướng request lại trang home URI.

<?php

namespace App\Http\Middleware;

use Closure;

class CheckAge
{
    public function handle($request, Closure $next)
    {
        if ($request->age <= 200) {
            return redirect('home');
        }
        return $next($request);
    }

}

Như bạn thấy, nếu biến age nhỏ hơn hoặc bằng 200, middleware sẽ trả về một HTTP tới client; ngược lại, request sẽ được gửi tiếp để xử lý. Để truyền request vào sâu hơn trong ứng dụng (cho phép middleware "vượt qua"), đơn giản chỉ cần gọi callback $next với $request.

Tốt nhất hãy hình dung như là một chuỗi các "lớp" trên HTTP requests cần phải đi qua trước khi nó vào ứng dụng. Mỗi lớp sẽ được kiểm tra request và thậm chí có thể hủy từ chối request hoàn toàn.

Trước & Sau Middleware

Việc middleware chạy trước hay chạy sau một request phụ thuộc vào chính nó. Ví dụ, middleware dưới đây sẽ làm một vào tác vụ trước khi request được chương trình xử lý:

<?php

namespace App\Http\Middleware;

use Closure;

class BeforeMiddleware
{
    public function handle($request, Closure $next)
    {
        // Perform action

        return $next($request);
    }
}

Tất nhiên, middleware này sẽ thực hiện việc của nó sau khi request được xử lý bởi ứng dụng:

<?php

namespace App\Http\Middleware;

use Closure;

class AfterMiddleware
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);

        // Perform action

        return $response;
    }
}

Đăng ký Middleware

Global Middleware

Nếu bạn muốn một middleware có thể thực thi trong mọi HTTP request tới ứng dụng của bạn, đơn giản chỉ cần thêm tên class của middleware trong thuộc tính $middleware của class app/Http/Kernel.php.

Gán Middleware vào Routes

Nếu bạn muốn gán middleware cho route cụ thể, đầu tiên bạn cần thêm middleware đấy vào trong file app/Http/Kernel.php. Mặc định, thuộc tính $routeMiddleware sẽ chứa một số class thuộc middleware của framework Laravel. Để thêm middleware của bạn, đơn giản chỉ là thêm nó vào dach sách và gán từ khóa bạn chọn. Ví dụ:

// Within App\Http\Kernel Class...

protected $routeMiddleware = [
    'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
    'can' => \Illuminate\Auth\Middleware\Authorize::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
];

Khi middleware đã được định nghĩa trong HTTP kernel, bạn có thể sử dụng phương thức middleware gán cho một route:

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

Ngoài ra bạn cũng có thể gán nhiều middleware cho một route:

Route::get('/', function () {
    //
})->middleware('first', 'second');

Khi đã gán middleware, bạn cũng có thể sử dụng tên đầy đủ của middleware:

use App\Http\Middleware\CheckAge;

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

Nhóm Middleware

Thỉnh thoảng bạn muốn nhóm một vài middleware lại trong một khóa để thực hiện gán vào route dễ dàng hơn. Bạn có thể sử dụng thuộc tính $middlewareGroups của HTTP kernel.

Mặc định, Laravel cung cấp sắp 2 nhóm middleware webapi chứa những middleware thường sử dụng mà bạn có thể muốn áp dụng cho web UI và API routes:

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:60,1',
        'auth:api',
    ],
];

Nhóm middleware được gán vào routes và controller sử dụng cú pháp tương tự như với từng middleware. Một lần nữa, nhóm middleware làm đơn giản trong việc gán các middleware vào trong một route:

Route::get('/', function () {
    //
})->middleware('web');

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

Tham số middleware

Middleware cũng có thể nhận thêm các tham số truyền vào. Ví dụ, nếu ứng dụng của bạn cần xác thực có "role" cụ thể trước khi thực hiện một thao tác nào đó, bạn có thể tạo một CheckRole middleware để nhận tên của role như một tham số.

Thêm các tham số middleware sẽ dược truyền vào middleware ngay sau tham số $next của hàm handle:

<?php

namespace App\Http\Middleware;

use Closure;

class CheckRole
{

    public function handle($request, Closure $next, $role)
    {
        if (! $request->user()->hasRole($role)) {
            // Redirect...
        }

        return $next($request);
    }
}

Tham số middleware có thể được khai báo trên route bằng cách phân chia tên middleware và tham số bởi dấu :. nhiều thao số thì phân chia bởi dấy phẩy:

Route::put('post/{id}', function ($id) {
    //
})->middleware('role:editor');

Terminable Middleware

Thỉnh thoảng một middleware có thể cần thực hiện sau khi HTTP response đã được gửi xong cho trình duyệt. Ví dụ, "session" middleware đi kèm với Laravel cung cấp dữ liệu session cho storage sau khi response được gửi tới trình duyệt. Nếu bạn định nghĩa một terminate vào trong middleware, nó sẽ tự động được gọi sau khi response được gửi tới trình duyệt.

<?php

namespace Illuminate\Session\Middleware;

use Closure;

class StartSession
{
    public function handle($request, Closure $next)
    {
        return $next($request);
    }

    public function terminate($request, $response)
    {
        // Store the session data...
    }
}

Hàm terminate sẽ nhận cả request và response. Khi bạn đã định nghĩa terminable middleware, bạ phải thêm nó vào trong danh sách global middleware trong HTTP kernel.

Khi gọi hàm terminate trong middleware, Laravel sẽ thực hiện giải quyết trường hợp mới cho middleware từ service container. Nếu bạn muốn sử dụng cùng một trường hợp khi mà hàm handle và hàm terminate được gọi, đăng ký middleware vào trong container sử dụng hàm singleton.

Nguồn: https://laravel.com/docs/5.2/middleware


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí