Middleware trong Laravel – Tìm hiểu qua ví dụ thực tế

Middleware trong laravel là một công nghệ lõi của framework. Bài viết này là góc nhìn của mình để giúp các bạn có thể hiểu rõ và vận dụng tốt lớp trung gian này. Sau khi đọc xong bài viết, các bạn có thể tạo một middleware, đăng ký nó và sử dụng trong dự án của mình. Mình sẽ cố gắng minh họa chi tiết nhất bằng code.

Middleware là gì? Thế còn Middleware trong laravel?

Khái niệm

Middleware là phần cung cấp các dịch vụ và khả năng phổ biến cho các ứng dụng bên ngoài những gì được cung cấp bởi hệ điều hành. Quản lý dữ liệu, dịch vụ ứng dụng, nhắn tin, xác thực và quản lý API đều thường được xử lý bởi Middleware. Đây là một phần trung gian giúp các nhà phát triển xây dựng ứng dụng hiệu quả hơn. Nó hoạt động giống như lớp liên kết giữa các ứng dụng, dữ liệu và người dùng.

Đây là khái niệm mình translate từ top 0 của google :3. Có vẻ không quá phù hợp với ” Middleware trong laravel”. Chúng ta cần chú ý tới từ “trung gian” và “lớp liên kết“.

Bạn hãy tưởng tượng bạn đang đi trên cao tốc Pháp Vân – Cầu Giẽ :3. Thì Middleware nó cũng như trạm thu phí BOT. Bạn nạp tiền, ok, đi tiếp. Chưa đóng phí, nằm im đó đi. 🙂 . Hoặc Middleware chính là cây cầu Nhật Tân nối 2 bờ sông Hồng vậy :p

laravel middleware chính là một nhịp cầu nối giữa request và responseMiddleware laravel khiến ta liên tưởng đến dòng xe đi qua một cây cầu

Middleware trong laravel

Trong một dự án laravel, Middleware cung cấp một cơ chế thuận tiện để kiểm tra và lọc các HTTP request yêu cầu tới ứng dụng của bạn. Ví dụ: Middleware để yêu cầu xác thực người dùng trước khi truy cập. Nếu người dùng không được xác thực, middleware sẽ chuyển hướng người dùng đến màn hình đăng nhập ứng dụng của bạn. Ngược lại, nếu người dùng được xác thực, nó sẽ cho phép yêu cầu tiến sâu hơn vào ứng dụng.

Tất cả các Middleware này đều nằm trong thư mục app/Http/Middleware.

Dưới đây là một vài trường hợp sử dụng Middleware:

  • Sử dụng Middleware để confirm và verify API.
  • Giới hạn số lần call service.
  • Thay đổi ngôn ngữ trang web dựa trên ip or location…
  • Cho phép bảo trì trên toàn bộ trang web.
  • Đánh hơi lưu lượng truy cập của bot.
  • Logging and tracking

Sử dụng Middleware laravel như thế nào?

Mình sẽ thử tạo một Middleware để kiểm soát ngôn ngữ hiển thị của trang web để demo cách sử dụng Middleware

Tạo một Middleware

Ngoài cách tạo một Middleware thủ công (nên hạn chế), thì bạn có thể tạo một Middleware bằng artisan. Chúng ta chỉ cần mở một cửa sổ terminal tại root của dự án và chạy lệnh sau:

// Replace Maintenance with the actual name of the Middleware.
php artisan make:middleware Maintenance

Command trên sẽ tạo ra một class middleware tại đường dẫn: app/Http/Middleware. Giờ hãy thêm logic vào class vừa tạo.

<?php

namespace App\Http\Middleware;

use Closure;
use Session;
use App;
use Config;

class SetLocale
{
    /**
     *
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if (Session::has('locale')) {
            $locale = Session::get('locale', Config::get('app.locale'));
        } else {
            $locale = substr($request->server('HTTP_ACCEPT_LANGUAGE'), 0, 2);

            if ($locale != 'fr' && $locale != 'en') {
                $locale = 'en';
            }
        }

        App::setLocale($locale);

        return $next($request);
    }
}

Tất cả logic bạn cần thực hiện ở middleware cần được đặt vào function handle. Giải thích qua một chút, trong middleware này, mình kiểm tra xem trong session đã lưu giá trị của ngôn ngữ hay chưa. Nếu đã lưu thì set ngôn ngữ của trang bằng App::seLocale. Nếu chưa thì xử lý lấy từ request.

Đăng ký một middleware

Sau khi đã tạo một middleware, Chúng ta cần cho laravel biết rằng class đó đã tồn tại. Nếu bạn muốn middleware đó chạy đối với mọi request được gửi đến, hãy vào file: app/Http/kernel.php và thêm middleware bạn vừa tạo vào $middleware property. Bằng cách này, ứng dụng của bạn sẽ kiểm tra ngôn ngữ ở mọi request.

protected $middleware = [
    ...
    \App\Http\Middleware\SetLocale::class
];

Nếu bạn muốn middlware của mình sẽ kiểm tra một hoặc một số routes nhất định, chúng ta có thể đặt tên cho middleware đó. Sử dụng tên này như một reference mechanism để thêm nó vào routes. Để đặt tên cho middleware, vẫn ở file app/Http/kernel.php, hãy thêm vào mảng $routeMiddleware với key là tên bạn muốn đặt. Như sau:

protected $routeMiddleware = [
    ...
    'language' => \App\Http\Middleware\SetLocale::class,
    ...
];

Thêm một Middleware trong laravel vào một Route

Route::get('posts/{something}', ['middleware' => 'grown.ups.only', function () {
    return "BlogLapTrinh";
}]);

Bằng cách này, chỉ có những routes posts/{something} mới được kiểm tra ngôn ngữ mỗi khi có người dùng truy cập. Một cahs khác để thêm middleware vào route đó là gọi phương thức middleware khi định nghĩ route:

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

Truyền Params vào Middleware?

Để truyền parameters vào các class middleware trong laravel 5.x (đến 8.x) là khá đơn giản. Với ví dụ trên, nếu ta muốn thêm biến $lang để kiểm tra trực tiếp input ngôn ngữ từ người dùng. Ta có thể thêm biến riêng này sau $requestClosure:

public function handle($request, Closure $next, $lang)
{
    if ($lang === 'vi') {
        // Redirect...
    }
    ..........
    return $next($request);
}

Để truyền vào từ route, chúng ta cần sửa lại như sau:

Route::put('index/{lang}', ['middleware' => 'language', function ($lang) {
    //
}]);

Nhóm cách Middlewares – Grouping Middlewares

Đôi khi, chúng ta cần nhiều middlewares cho một nhóm routes. Như vậy, sẽ tốt hơn nếu chúng ta có thể kết hợp hoặc group các Middleware lại với nhau. Để nhóm Middlewares lại, chúng ta thêm vào $middlewareGroups vẫn trong file kernel.php. Nếu không tìm thấy property này, hãy thêm vào như sau:

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,
    ],

    'api' => [
        'throttle:60,1',
        'auth:api',
    ],
];

Mặc định, laravel cung cấp 2 group có sẵn là “web” và “api”. Sử dụng group middlewares như sau:

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

Sử dụng Middleware sau khi application nhận được request

Ví dụ xuyên suốt của chúng ta được thực hiện khi middlewares được gọi trước khi request được truyền đến applicaiton. Nhưng chúng ta hoàn toàn có thể làm ngược lại:

<?php

namespace App\Http\Middleware;

use Closure;

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

        // Perform action

        return $response;
    }
}

Ở đây, request đã được handled bởi application. Sau đó, mới được tiếp nhận và xử lý trong middleware.

Tổng kết

Trên đây là một ví dụ cụ thể để tạo một middleware trong laravel và cách sử dụng chúng trong thực tế như thế nào. Nếu bạn có bất cứ câu hỏi nào, đừng ngại ngần comment và cho mình biết nhé <3

Tham khảo:

Document của Laravel