Chào anh em , gặp lại anh em trong bài viết chia sẻ lần này trong series Laravel và những điều thú vị ,lần này ta sẽ tiếp phần middleware nhá.
Middleware dùng để làm gì ?
Trước khi đi vào việc tạo và sử dụng Middleware trong Laravel thì chúng ta sẽ cùng tìm hiểu về công dụng của nó qua. Giả sử chúng ta có một trang web xem phim ( ????) ,trả phí với một vài tính năng như:
- Xem danh sách các bộ phim mà hệ thống của bạn có
- Xem một bộ phim
- Download phim về máy
Và tương ứng chúng ta sẽ có vài chức năng như sau:
class MovieController extends Controller { public function getList(Request $request) { // Lấy danh sách các bộ phim } public function watchMovie(Request $request) { // Xem một bộ phim } public function downloadMovie(Request $request) { // Download bộ phim bạn chọn } }
Vì trang web chúng ta là trang web phải trả phí nên đồng nghĩa với việc người dùng phải là tài khoản đã đăng nhập rồi để có thể thực hiện chức năng nói trên. Với cách làm thông thường thì ta có thể thêm đoạn code kiểm trả xem người dùng đã đăng nhập chưa ở mỗi chức năng như sau:
class MovieController extends Controller { public function getList(Request $request) { if (Auth::check()) { // Lấy danh sách các bộ phim } } public function watchMovie(Request $request) { if (Auth::check()) { // Xem một bộ phim } } public function downloadMovie(Request $request) { if (Auth::check()) { // Download bộ phim bạn chọn } } }
Nếu trang web của bạn chỉ có 3 chức năng thì cũng ok không có vấn đề gì to tát lắm. Nhưng thử tưởng tượng bạn có đến 50 chức năng đều cần kiểm tra đăng nhập thì sao ? Bạn có thể vẫn try-hard
bằng cách viết lại phần code kia cho cả 50 chức năng như trên và mọi thứ lại chạy đâu vào đó. Tuy nhiên một hôm đẹp trời, 50 tính năng này của bạn lại cần phải check xem nếu người dùng đã đăng nhập và trong tài khoảng trong phim phải có lớn hơn 50k VND thì sao.(viết hết 50 hàm chắc hết đêm,hao tổn sinh lực :)) ).

Để giải quyết bài toán như nói trên thì chúng ta sẽ có khái niệm Web Middleware . Đơn giản nhất bạn có thể hiểu nó phần trong ứng dụng của bạn cho phép bạn gom toàn bộ 50 lần đoạn code nói trên về chung một nột chức năng duy nhất và có thể tái sử dụng lại. Middleware sẽ có vai trò đứng giữa các request từ người dùng đến hệ thống của bạn và kiểm tra xem nó có thỏa mãn các điều kiện mà bạn mong muốn trước khi có thể truy cập vào tính năng mà bạn cung câp:
- Người dùng đã đăng nhập
- Tài khoảng của người dùng có > 50k VND

Như bạn thấy tất cả những yêu cầu của người dùng đều phải đi qua đây trước khi có thể thực hiện các tính năng mà bạn cung cấp. Đồng nghĩa với việc ở đây, chúng ta có thể lầm bất cứ thứ gì mà chúng ta muốn với request này trước khi bạn cho nó tiếp tục di chuyển đến tính năng của bạn hoặc từ chối không cho nó đi tiếp.
Middleware trong Laravel
Để tạo mới một middleware, ta sử dụng cú pháp:
Ví dụ
Sau khi bạn chạy lệnh trên thì Laravel sẽ tạo ra cho chúng ta một file mới nằm trong đường dẫn app/Http/Middleware/VerifyAccountBalance.php
và có nội dung như sau:
<?php namespace App\Http\Middleware; use Closure; class VerifyAccountBalance { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { return $next($request); } }
Middleware mà chúng ta tạo ra ở đây chỉ có duy nhất 1 function là handle()
và 2 tham số truyền vào lần lượt là
$request- request từ phía người dùng
Và 1 closure tên là $next
dùng để cho request của người dùng tiếp tục truy cập đến chức năng trong ứng dụng của bạn khi nó thỏa mãn hết các yêu cầu bạn đặt ra.
+Phần return $next($reuqest);
sẽ cho phép request của người dùng được tiếp tục được thực hiện. Như ví dụ từ trước đó ta sẽ cần kiểm tra 2 thứ đó là người dùng đã đăng nhập và tài khoản có lớn hơn 50K VND. Ta có thể viết lại nội dung hàm handle()
như sau:
public function handle($request, Closure $next) { if (Auth::check() && Auth()::user()->getAccountBalance() > 50000) { return $next($request); } return redirect('home')->with('message', __('Some error message')); }
Ở đoạn code trên thì nếu request từ phía người dùng thỏa mãn 2 điều kiện mà chúng ta đặt ra thì chúng ta sẽ cho họ tiếp tục truy cập vào tính năng còn trong trường hợp ngược lại thì chúng ta sẽ redirect người dùng quay về trang home kèm theo một đoạn message nào đó mà bạn mong muốn
Tiếp đến để dùng được nó thì ta sẽ cần khai báo nó trong file app/Http/Kernel.php.
protected $routeMiddleware = [ 'auth' => \App\Http\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, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, // addnew o day 'verfiy-account-balance' => App\Http\Middleware\VerifyAccountBalance::class, ];
Giờ đây thay vì bạn phải Viết đi code lại đoạn code kiểm tra 2 điều kiện mà bạn đặt ra trong tất các các hàm ở các controller thì bạn có thể đơn giản hóa nó ngay từ trong router
như sau:
Route::group(['middleware' => 'verfiy-account-balance'], function() { Route::get('download-movie', 'MovieController@downloadMovie'); // ......... });
Ở đây bạn nhớ đặt phần ‘middleware’ => ‘verfiy-account-balance’ trùng với tên mà chúng ta đã khai báo trong file Kernel.php. Giờ đây trước khi request từ người dùng được sử lý trong controller của chúng ta thì nó sẽ được kiểm tra theo điều kiện mà chúng ta đặt ra rồi mới có thể đi tiếp. Ngoài cách viết như trên thì để sử dụng middleware cho một route duy nhất thì ta cũng có thể viết:
Route::get('get-list-movie', 'MovieController@getList')->middleware('verfiy-account-balance');
Vậy là xong rồi.