Create Middleware in Laravel 5.8

min read

Day 14 #100DaysOfCode
Mấy bửa này không tiếp tục được, bị gián đoạn một thời gian, nay mình tiếp tục tìm hiểu về Middleware trong Laravel, Middleware là một chức năng giúp ta xác thực một số Route trong Laravel, nó cũng giống như một lớp bao phủ toàn bộ bề mặc của ứng dụng của ta, xem xét có nên cho thực thi điều gì đó hay không!
Nói đúng hơn là, mọi Request(yêu cầu) sẽ được thông qua Middleware , và tiếp tục Response(phản hồi) cũng thông qua Middleware, rồi mới tới người dùng cuối
Okay tiếp tục ta tạo Middleware trong Laravel như sau:

php artisan make:middleware ProductDeleteMethod

Sau khi tạo xong bạn sẽ thấy nó trong đường dẫn sau : app/Http/Middleware/ProductDeleteMethod.php, bạn mở nó lên sẽ có cấu trúc mặc định như đoạn code sau:

<?php

namespace App\Http\Middleware;

use Closure;

class ProductDeleteMethod
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        return $next($request);
    }
}

Bạn nhìn đoạn code trên thấy phương thức handle() xử lý yêu cầu đến và phản hồi yêu cầu đi
Bạn cũng có thể tạo nhiều Middleware khác nhau, xử lý các vấn đề khác nhau, nhưng bạn hãy nhớ rằng, các middleware sẽ được xếp chồng lên nhau
Middleware nào được đăng ký trước, sẽ có quyền truy cập đầu tiên vào một yêu câu khi nó xuất hiện, thì yêu cầu đó lần lượt chuyển đến mọi Middleware khác, rồi vào ứng dụng. Sau đó phản hồi kết quả được chuyển ra bên ngoài thông qua Middleware, và cuối cùng Middleware đầu tiên này có quyền truy cập cuối cùng vào phản hồi khi nó bị lỗi

 

Mình vừa đăng ký ProductDeleteMethod làm Middleware đầu tiên và chạy nó, có nghĩa là ta cần $request yêu cầu đi vào nó
Sau đó chuyển yêu cầu đến $next(), có nghĩa là chuyển nó cho phần còn lại của Middleware. 
Trong $next() chỉ nhận $request rồi chuyển nó đến phương thức handle() của Middleware tiếp theo trong ngăn xếp. Sau đó nó được truyền xuống các middleware tiếp theo, coi có hoặc không có Middleware nào nữa để giao. Thì cuối cùng nó sẽ xuất hiện trên ứng dụng của ta

 

Khó hiểu quá trời quá đất, đọc tới lui mà mình còn khó hiểu, chỉ làm ví dụ mới dễ hình dung ra thôi!, làm càng nhiều mới hiểu rỏ hơn, cả mình còn khó hiểu nửa, nên phải tìm hiểu nhiều hơn nửa mới được, bạn có thể tìm hiểu thêm tại đây : https://laravel.com/docs/5.8/middleware

Hãy mở file app/Http/Middleware/ProductDeleteMethod.php

<?php

namespace App\Http\Middleware;

use Closure;

class ProductDeleteMethod
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        // kiểm tra xem, nếu id===99, thì không được xóa
        if($request->id==99){
            return response('Không được xóa ID này!', 403);
        }

        $response = $next($request);
 
        return $response;
    }
}

+ Đầu tiên ta kiểm tra xem, yếu id===99, thì chúng ta không được xóa,return về 403

 if($request->id===99){
            return response('Không được xóa ID này!', 403);
        }


+ Ngược lại chấp nhận yêu cầu, hãy chuyển nó đến Middleware tiếp theo trong ngăn xếp. Chúng ta chuyển nó cho $next(), và nhận trả về phản hồi sau khi $request được chuyển xuống ngăn xếp Middleware ứng dụng và phản hồi của ứng dụng đã được chuyển trở lại ngăn xếp
+ Cuối cùng bạn có thể chuyển phản hồi tới người dùng 

 $response = $next($request);
 return $response;

Tiếp theo mở file app/Http/Kernel.php lên đăng ký middleware của ta vừa tạo bên trên

// app/Http/Kernel.php
protected $middleware = [
    ...
    \App\Http\Middleware\BanDeleteMethod::class,
];

// app/Http/Kernel.php
protected $routeMiddleware = [
    ...
    'product-delete' => \App\Http\Middleware\ProductDeleteMethod::class,
];

+ $middleware : Nếu ta đặt khai báo middleware trong đây, nó sẽ chạy mọi yêu cầu, ta cũng thường hay gặp lỗi như : ERR_TOO_MANY_REDIRECTS, nó chuyển hướng nhiều lần, bởi vì middleware nào đó nó đã khai báo rồi, rồi ta đã vô tình khai báo nửa, sẽ dễ bị lỗi ERR_TOO_MANY_REDIRECTS

+ $middlewareGroup : chạy trên mọi yêu cầu cho nhóm (web, api, v.v.). Mọi thứ trong các route / web.php sẽ chạy qua nhóm 'web'.

+ $routeMiddleware:  chỉ cụ thể một route nào đó sử dụng middleware
VD: Route::get('/test/user', UsersController@index)->middleware('check-permission:add_category')->name("user.index");

giờ ta có thể dùng Middleware xác thực Route như sau:

// routes/web.php
Route::get('/','ProductController@index'); 
Route::delete('/products','ProductController@destroy')->middleware('product-delete')->name("product.delete"); 
//or
Route::prefix('api')->middleware('product-delete')->group(function () {
    All routes related to an API
});

Và tôi có một file controller app/Http/Controllers/ProductController.php như sau:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Product;
use App\Comment;
class ProductController extends Controller
{
    public function index(){
       return view("form");
    }
    
    public function destroy(Request $request){
        return Response()->json(array("success"=>1));
    }
}

Tạo blade resources/views/form.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <form action="{{route('product.delete')}}" method="POST">
        @csrf
        @method('DELETE')
        <input type="text" name="id" value="99" />
        <input type="submit" name="submit" value="Delete Product" />

    </form>
</body>
</html>

Demo:

 

Bạn cũng có thể kiểm tra method khi request!

public function handle($request, Closure $next)
    {
        
    // kiểm tra xem, nếu id===99, thì không được xóa 
     if ($request->method() == 'DELETE' && $request->id==99) {
        return response("method 'delete', id:$request->id",405);
      }
        $response = $next($request);
 
        return $response;
    }

Bên cạnh đó bạn có thể tạo Middleware kiểm tra (Age, login,API,...) 

 

x

Ủng hộ tôi bằng cách click vào quảng cáo. Để tôi có kinh phí tiếp tục phát triển Website!(Support me by clicking on the ad. Let me have the money to continue developing the Website!)