Explore all courses in this category.
Explore all courses in this category.
Nguyễn Đình Cường
0 comment
09 Nov, 2026
Trước khi một request chạm tới controller, nó có thể đi qua nhiều trạm kiểm soát: đã đăng nhập chưa, có đủ quyền không, có gửi quá nhiều lần không? Mỗi trạm đó là một middleware. Hiểu middleware là hiểu cách Laravel xử lý mọi yêu cầu HTTP.
Hãy tưởng tượng một chiếc hành lang có nhiều cánh cửa. Request đi vào, qua từng cánh cửa theo thứ tự, tới controller rồi phản hồi đi ngược ra qua các cửa đó. Mỗi middleware có thể làm việc trước khi gọi tiếp (kiểm tra, từ chối), hoặc sau khi nhận phản hồi (thêm header, ghi log).
Laravel có sẵn nhiều middleware: auth (yêu cầu đăng nhập), throttle (giới hạn tần suất), verified (yêu cầu xác minh email), can (kiểm tra quyền)...
Giả sử bạn muốn chỉ cho phép quản trị viên vào một nhóm route. Tạo middleware:
php artisan make:middleware EnsureUserIsAdminclass EnsureUserIsAdmin{ public function handle(Request $request, Closure $next): Response { if (! $request->user()?->is_admin) { abort(403, 'Bạn không có quyền truy cập.'); } return $next($request); }}Lời gọi $next($request) chính là chuyển request sang tầng tiếp theo. Nếu bạn không gọi nó, request dừng lại tại đây.
Từ Laravel 11, bạn đăng ký alias trong bootstrap/app.php:
->withMiddleware(function (Middleware $middleware) { $middleware->alias([ 'admin' => \App\Http\Middleware\EnsureUserIsAdmin::class, ]);})Ở các phiên bản cũ hơn, việc này nằm trong app/Http/Kernel.php. Sau khi đăng ký, gắn vào route rất đơn giản:
Route::middleware(['auth', 'admin'])->prefix('admin')->group(function () { Route::get('/users', [UserController::class, 'index']);});Bạn có thể truyền tham số sau dấu hai chấm, ví dụ role:editor,admin, và nhận chúng làm đối số thêm của handle:
public function handle(Request $request, Closure $next, string ...$roles): Response{ if (! in_array($request->user()->role, $roles, true)) { abort(403); } return $next($request);}Để xử lý sau khi controller chạy xong, lấy phản hồi trước rồi chỉnh sửa:
$response = $next($request);$response->headers->set('X-Frame-Options', 'DENY');return $response;web (session, CSRF) và api (throttle), áp dụng cho cả nhóm route.Thứ tự rất quan trọng. Ví dụ middleware kiểm tra quyền phải chạy sau auth, vì nó cần biết người dùng là ai. Khi gặp lỗi lạ, hãy kiểm tra xem thứ tự có hợp lý không.
Dùng middleware cho các mối quan tâm cắt ngang nhiều route: xác thực, phân quyền thô, giới hạn tần suất, đặt ngôn ngữ, ghi log request. Không nên nhét logic nghiệp vụ vào đó, vì middleware khó kiểm thử hơn và làm luồng xử lý trở nên mờ ám. Quy tắc nhỏ: nếu logic chỉ liên quan một hành động cụ thể, hãy để ở controller hoặc service.
Một middleware rất hữu ích cho người mới là đo thời gian mỗi request, giúp bạn phát hiện endpoint chậm:
class LogRequestTime{ public function handle(Request $request, Closure $next): Response { $start = microtime(true); $response = $next($request); $ms = round((microtime(true) - $start) * 1000); Log::info('request', [ 'path' => $request->path(), 'status' => $response->getStatusCode(), 'ms' => $ms, ]); return $response; }}Chỉ với khoảng mười dòng, bạn có số liệu để quyết định nên tối ưu endpoint nào trước. Đây là minh họa rõ ràng cho việc middleware có thể làm việc cả trước lẫn sau controller.
Bạn không cần dựng cả ứng dụng để kiểm thử middleware. Chỉ cần gọi route được bảo vệ bằng người dùng thường rồi bằng quản trị viên, và khẳng định mã trả về lần lượt là 403 và 200. Hai test nhỏ này đủ bảo vệ bạn khỏi việc vô tình mở toang một khu vực quản trị khi ai đó đổi cấu hình route.
Lỗi phổ biến nhất là quên trả về $next($request), khiến request không bao giờ đến controller và ứng dụng trả về trang trống. Lỗi thứ hai là gắn sai thứ tự, ví dụ kiểm tra quyền trước khi xác thực. Lỗi thứ ba là đặt quá nhiều việc vào middleware toàn cục, làm mọi request chậm đi dù chỉ một vài route cần đến. Hãy giữ middleware nhỏ, mỗi cái một nhiệm vụ rõ ràng, và đặt tên theo điều nó đảm bảo như EnsureUserIsAdmin.
Middleware là cơ chế gọn gàng để áp dụng quy tắc chung cho nhiều request mà không lặp code. Hãy thử tự viết một middleware ghi log thời gian xử lý của mỗi request, bạn sẽ nắm rất nhanh cách đường ống này vận hành.
Nếu muốn luyện tập cùng bài tập thực tế, hãy ghé các khóa học tại codebem.com khi bạn sẵn sàng.
Nguyễn Đình Cường
0 comment