Middleware
16458

Middleware cung cấp một cơ chế lọc các yêu cầu HTTP vào ứng dụng của bạn. Ví dụ, Laravel bao gồm một middleware kiểm tra người dùng của bạn có xác thực hay chưa. Nếu người dùng không xác thực, middleware sẽ chuyển hướng người dùng đến trang đăng nhập. Tuy nhiên, nếu người dùng đã xác thực, middleware sẽ cho phép yêu cầu tiếp tục vào ứng dụng.

Dưới đây là các bước để định nghĩa middleware trong Laravel:

1. Tạo Middleware

Để tạo middleware, bạn có thể sử dụng lệnh Artisan sau:

php artisan make:middleware CheckAge

Lệnh này sẽ tạo ra một lớp middleware mới tại app/Http/Middleware/CheckAge.php. Trong lớp middleware này, bạn chỉ cần định nghĩa phương thức handle.

2. Định nghĩa Middleware

Trong lớp middleware, bạn có thể viết logic để kiểm tra hoặc xử lý yêu cầu. Ví dụ, dưới đây là cách middleware kiểm tra độ tuổi của người dùng:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class CheckAge
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next)
    {
        if ($request->age <= 200) {
            return redirect('home');
        }

        return $next($request);
    }
}

Trong ví dụ này, nếu độ tuổi của người dùng nhỏ hơn hoặc bằng 200, middleware sẽ chuyển hướng họ về trang chủ. Nếu không, yêu cầu sẽ tiếp tục được xử lý.

3. Đăng ký Middleware

Sau khi tạo middleware, bạn cần đăng ký nó trong ứng dụng. Có hai cách để đăng ký middleware: toàn cục và nhóm.

3.1. Middleware Global

Để đăng ký middleware toàn cục, bạn thêm nó vào thuộc tính $middleware trong app/Http/Kernel.php:

protected $middleware = [
    // Other middleware
    \App\Http\Middleware\CheckAge::class,
];
3.2. Middleware Groups

Để đăng ký middleware nhóm, bạn thêm nó vào thuộc tính $middlewareGroups trong app/Http/Kernel.php. Ví dụ, bạn có thể thêm middleware vào nhóm web:

protected $middlewareGroups = [
    'web' => [
        // Other middleware
        \App\Http\Middleware\CheckAge::class,
    ],

    'api' => [
        'throttle:api',
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],
];
3.3. Middleware Định Tuyến

Bạn có thể gán middleware cho các tuyến cụ thể bằng cách sử dụng phương thức middleware trong file routes/web.php hoặc routes/api.php:

Route::get('admin/profile', function () {
    // Only authenticated users may enter...
})->middleware('auth', 'check.age');

4. Middleware Tham Số

Middleware cũng có thể chấp nhận tham số. Ví dụ, bạn có thể tạo middleware để kiểm tra vai trò của người dùng:

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

    return $next($request);
}

Sau đó, bạn có thể gán middleware này cho một tuyến với tham số:

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

# Middleware and Responses

Middleware có thể thực hiện các tác vụ trước hoặc sau khi chuyển tiếp yêu cầu vào sâu hơn trong ứng dụng. Ví dụ, middleware sau đây sẽ thực hiện một số tác vụ trước khi yêu cầu được xử lý bởi ứng dụng:

Ví dụ Middleware

Dưới đây là một ví dụ về middleware thực hiện một số tác vụ trước khi xử lý yêu cầu:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class BeforeMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next)
    {
        // Thực hiện một số tác vụ trước khi yêu cầu được xử lý
        // Ví dụ: kiểm tra điều kiện hoặc ghi log
        if ($request->user() && $request->user()->isBlocked()) {
            return response('Your account is blocked.', 403);
        }

        // Chuyển tiếp yêu cầu vào sâu hơn trong ứng dụng
        return $next($request);
    }
}

Thực hiện tác vụ sau khi xử lý yêu cầu

Middleware cũng có thể thực hiện các tác vụ sau khi yêu cầu đã được xử lý. Để làm điều này, bạn chỉ cần thêm logic sau khi gọi hàm $next($request):

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class AfterMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next)
    {
        // Xử lý yêu cầu
        $response = $next($request);

        // Thực hiện một số tác vụ sau khi yêu cầu đã được xử lý
        // Ví dụ: thêm header vào phản hồi
        $response->header('X-Header-One', 'Header Value');

        return $response;
    }
}

Trong ví dụ trên, middleware sẽ thêm một header vào phản hồi sau khi yêu cầu đã được xử lý bởi ứng dụng.

# Sorting Middleware

Trong Laravel, bạn có thể chỉ định thứ tự thực hiện của các middleware. Việc sắp xếp này có thể hữu ích khi bạn cần một middleware phải được thực thi trước hoặc sau một middleware khác. Laravel cung cấp một cách dễ dàng để sắp xếp thứ tự của các middleware thông qua thuộc tính $middlewarePriority trong lớp App\Http\Kernel.

Định nghĩa Thứ Tự Middleware

Để sắp xếp thứ tự thực hiện của middleware, bạn chỉ cần thêm thuộc tính $middlewarePriority vào lớp App\Http\Kernel và liệt kê các middleware theo thứ tự bạn muốn chúng được thực thi:

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    /**
     * The application's global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array
     */
    protected $middleware = [
        // Danh sách các middleware toàn cục
    ];

    /**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            // Danh sách các middleware nhóm 'web'
        ],

        'api' => [
            // Danh sách các middleware nhóm 'api'
        ],
    ];

    /**
     * The application's route middleware.
     *
     * These middleware may be assigned to groups or used individually.
     *
     * @var array
     */
    protected $routeMiddleware = [
        // Danh sách các route middleware
    ];

    /**
     * The priority-sorted list of middleware.
     *
     * This forces non-global middleware to always be in the given order.
     *
     * @var array
     */
    protected $middlewarePriority = [
        \App\Http\Middleware\FirstMiddleware::class,
        \App\Http\Middleware\SecondMiddleware::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\AnotherMiddleware::class,
        // Thêm các middleware khác theo thứ tự bạn muốn
    ];
}

Trong ví dụ trên, FirstMiddleware sẽ được thực thi trước SecondMiddleware, và AnotherMiddleware sẽ được thực thi sau StartSessionShareErrorsFromSession.

Ví Dụ Về Middleware

Dưới đây là ví dụ về hai middleware mà bạn muốn sắp xếp thứ tự thực hiện:

  1. FirstMiddleware:

    <?php
    
    namespace App\Http\Middleware;
    
    use Closure;
    
    class FirstMiddleware
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
        public function handle($request, Closure $next)
        {
            // Logic của FirstMiddleware
            return $next($request);
        }
    }
    
  2. SecondMiddleware:
    <?php
    
    namespace App\Http\Middleware;
    
    use Closure;
    
    class SecondMiddleware
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
        public function handle($request, Closure $next)
        {
            // Logic của SecondMiddleware
            return $next($request);
        }
    }
    

Kết Hợp Với Route

Sau khi định nghĩa thứ tự của middleware, bạn có thể gán chúng cho các tuyến hoặc nhóm tuyến trong tệp routes/web.php hoặc routes/api.php:

// routes/web.php

Route::middleware(['first', 'second'])->group(function () {
    Route::get('/', 'HomeController@index');
});

// Hoặc sử dụng trực tiếp trong các tuyến:
Route::get('/example', 'ExampleController@index')->middleware('first', 'second');

# Terminable Middleware

Trong Laravel, middleware có thể được chia thành hai loại chính: middleware thực thi trong quá trình xử lý yêu cầu và middleware thực thi sau khi phản hồi đã được gửi đến client. Middleware thuộc loại thứ hai được gọi là "terminable middleware".

Terminable middleware cho phép bạn thực hiện các công việc sau khi phản hồi đã được gửi về phía client, chẳng hạn như ghi log hoặc thực hiện các tác vụ tốn thời gian mà bạn không muốn làm chậm thời gian phản hồi của ứng dụng.

Tạo Middleware Terminable

Để tạo một terminable middleware, bạn cần tạo một middleware như bình thường và thêm phương thức terminate vào lớp middleware đó. Phương thức terminate sẽ được tự động gọi sau khi phản hồi đã được gửi về phía client.

  1. Tạo Middleware bằng Artisan:
    php artisan make:middleware LogAfterRequest
    
  2. Định nghĩa Middleware với phương thức terminate:
    <?php
    
    namespace App\Http\Middleware;
    
    use Closure;
    use Illuminate\Http\Request;
    use Symfony\Component\HttpFoundation\Response;
    
    class LogAfterRequest
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
        public function handle(Request $request, Closure $next)
        {
            // Thực hiện các công việc trước khi xử lý yêu cầu
            return $next($request);
        }
    
        /**
         * Handle tasks after the response has been sent to the client.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Symfony\Component\HttpFoundation\Response  $response
         * @return void
         */
        public function terminate(Request $request, Response $response)
        {
            // Thực hiện các công việc sau khi phản hồi đã được gửi đến client
            \Log::info('Request has been completed.');
        }
    }
    

Đăng Ký Middleware

Bạn cần đăng ký middleware trong tệp app/Http/Kernel.php để Laravel có thể nhận diện và sử dụng middleware đó:

  1. Thêm middleware vào thuộc tính $middleware hoặc $routeMiddleware của lớp Kernel:
    // app/Http/Kernel.php
    
    protected $middleware = [
        // Các middleware khác
        \App\Http\Middleware\LogAfterRequest::class,
    ];
    
  2. Nếu bạn muốn middleware này chỉ áp dụng cho một số tuyến cụ thể, bạn có thể thêm vào thuộc tính $routeMiddleware:
    // app/Http/Kernel.php
    
    protected $routeMiddleware = [
        // Các route middleware khác
        'log.after' => \App\Http\Middleware\LogAfterRequest::class,
    ];
    
  3. Sử dụng middleware trong tuyến của bạn:
    // routes/web.php
    
    Route::get('/example', 'ExampleController@index')->middleware('log.after');
    

Kết Hợp với Các Tác Vụ Sau Phản Hồi

Bạn có thể sử dụng terminable middleware để thực hiện các tác vụ sau khi phản hồi đã được gửi đến client, chẳng hạn như:

  • Ghi log các yêu cầu và phản hồi
  • Gửi email
  • Thực hiện các tác vụ bảo trì
  • Đặt lại các kết nối hoặc phiên làm việc

Ví dụ, bạn có thể sử dụng phương thức terminate để ghi lại log các thông tin về yêu cầu và phản hồi:

public function terminate(Request $request, Response $response)
{
    \Log::info('Request URL: ' . $request->fullUrl());
    \Log::info('Response Status: ' . $response->status());
}

Danh mục


  1. Khác
  2. ThreeJS
  3. Ubuntu/Linux
  4. HTML/CSS
  5. Git
  6. Amazon Web Services
  7. Javascript
  8. Docker
  9. Laravel

Bài viết liên quan


Database: Seeding

Database: Seeding

01.08.2024
Author: ADMIN
Laravel Seeding giúp tự động tạo dữ liệu mẫu nhanh chóng. Tìm hiểu cách tạo, chạy seeder, kết hợp factory, và sử dụng trong production một cách an toàn! 🚀

Bài viết khác

Routing

Routing

01.08.2024
Author: ADMIN
Hướng dẫn chi tiết về Basic Routing trong Laravel, từ cách định nghĩa route, sử dụng middleware, route caching đến route naming giúp tối ưu hóa ứng dụng.
Blade Basics

Blade Basics

01.08.2024
Author: ADMIN
Khám phá Blade trong Laravel: từ if-else, loops, kế thừa layout đến include sub-views. Giúp code gọn gàng, dễ quản lý và bảo trì hơn!
9 Mẹo Hữu Ích Khi Sử Dụng Blade Trong Laravel

9 Mẹo Hữu Ích Khi Sử Dụng Blade Trong Laravel

01.08.2024
Author: ADMIN
Khám phá 9 mẹo Blade giúp bạn viết code Laravel sạch, tối ưu và chuyên nghiệp hơn. Từ @forelse, @auth, @guest, đến format ngày, tối ưu SEO – tất cả trong một bài viết súc tích, dễ áp dụng!
Hiển thị giá trị trong Blade

Hiển thị giá trị trong Blade

01.08.2024
Author: ADMIN
Hướng dẫn hiển thị biến trong Laravel Blade: escape HTML tự động, hiển thị dữ liệu thô, giá trị mặc định và cách truy xuất mảng, đối tượng. Giúp bạn tối ưu hiển thị dữ liệu một cách an toàn!