# 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 %}