---
# System prepended metadata

title: Laravel Middleware
tags: [中介層, middleware, '2021', laravel]

---

# Laravel Middleware

https://laravel.com/docs/8.x/middleware

檢查和過濾 HTTP 請求，像是判斷是不是已認證使用者，如果不是認證的可能會被導到某個地方，額外應用的方式可能有 logging middleware 去 log 所有進來的 request

# 檔案存放的位置

都存放在 app/Http/Middleware 這個木路底下

# 建立

```php=
php artisan make:middleware EnsureTokenIsValid
```

可以把 middleware 想成是 HTTP request 需要通過的一系列關卡，每個關卡都有自己要處理的事情符合就通過，不符合可能就拒絕請求這樣

# 種類

## before middleware

被 application 處理前就執行

```php=

class BeforeMiddleware
{
    public function handle($request, Closure $next)
    {
        // Perform action

        return $next($request);
    }
}
```

## after middleware

被 application 處理後才執行

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

        // Perform action

        return $response;
    }
}
```

# 註冊

需要在 app/Http/Kernel.php 裡面進行註冊或設定

## Global

如果有有 middleware 需要每次請求都被執行可以放在 $middleware 這個陣列裡

## 給 route 用

需要在 $routeMiddleware 這個屬性裡面設定 key name 和對應的檔案，下面範例

```php=
// App\Http\Kernel
protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class
];

// route 使用單一 middleware

Route::get('/profile', function () {
    //
})->middleware('auth');

// route 使用多個 middleware

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

// 也可以用 class 的寫法
use App\Http\Middleware\EnsureTokenIsValid;

Route::get('/profile', function () {
    //
})->middleware(EnsureTokenIsValid::class);

```

## 不包含某個 middleware

```php=
Route::get('/profile', function () {
        //
    })->withoutMiddleware([EnsureTokenIsValid::class]);
```

# Middleware Groups

可以看一下 App\Http\Kernel 裡 $middlewareGroups 這個屬性預設是有 web 和 api 這兩個 key 在看一下 RouteServiceProvider 裡有用到這兩個 key 代表這兩個 route file 都會套用 對應的 middleware group

```php=
// App\Http\Kernel

protected $middlewareGroups = [
    'web' => [
        ...
    ],

    'api' => [
        ...
    ],
];


// RouteServiceProvider
public function boot()
{
        $this->configureRateLimiting();

        $this->routes(function () {
            Route::prefix('api')
                ->middleware('api')
                ->namespace($this->namespace)
                ->group(base_path('routes/api.php'));

            Route::middleware('web')
                ->namespace($this->namespace)
                ->group(base_path('routes/web.php'));
        });
}
```

如果想要在 route file 裡使用也可以，就是將 key name 帶入就好，但其實各自 route file 就會帶入各自的 middleware group 了


```php=
Route::get('/', function () {
    //
})->middleware('web');

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

# 順序執行 middleware

如果需要有順序去執行的話可以在 `app/Http/Kernel.php` 新增一個 $middlewarePriority 屬性的陣列然後按照你想要的順序去排序 middleware，預設上沒有這個屬性

# middleware 參數

```

// middleware - $role 是額外帶進來的
public function handle($request, Closure $next, $role){

 // action
}

// route file

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


```

# Terminable Middleware

當回傳回瀏覽器時可能會需要做一些其它處理，可以在 middleware 檔案裡新增 terminate method 去做你想做的

```php=


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

    /**
     * Handle tasks after the response has been sent to the browser.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Illuminate\Http\Response  $response
     * @return void
     */
    public function terminate($request, $response)
    {
        // ...
    }
}
```

## 註冊 Terminable Middleware


在 app/Http/Kernel.php 裡註冊，註冊在 route 或 global middleware 屬性
裡


###### tags: `2021` `laravel` `middleware` `中介層`

{%hackmd BJrTq20hE %}
