---
# System prepended metadata

title: laravel middware
tags: [Laravel]

---

# laravel middware

中介層都是透過服務容器來解析的，因此，你可以在中介層建構子中以型別提示鍵入你需要的任何依賴

## terminate
![](https://i.imgur.com/ymnMxfe.png)
![](https://i.imgur.com/mjOPQFh.png)
可以用終止 在middware裡面 有點在所有middwre跑完會用到

你可以看到是在畫面跑完 response那邊會用到
![](https://i.imgur.com/6upEzIC.png)


## 帶參數

```
Route::group([
  // role:admin 代表你要在 Middleware 中設置變數 $role = admin
  'middleware' => ['auth:api', 'role:admin'],
], function () {
  Route::post('roles', [RolesController::class, 'store']);  
});
```
在middware那邊直接這樣帶入參數就好 
`public function handle($request, Closure $next, $role)`

## before 和 after的差別
Before Middleware 先執行自己的內容，在執行 route 的內容，而反過來的 After Middleware 則是先執行 route 的內容，才回去執行自己的內容

關鍵就是 $next 這個參數是在'前'還是'後'，由於 $next 本身是一個 closure 所以會執行一個動作就是把 $request 當成參數交給下一個程式執行


**Before Middleware**
```
<?php

namespace App\Http\Middleware;

use Closure;

class BeforeMiddleware
{
    public function handle($request, Closure $next)
    {
        // Perform action       //先執行任務  
        echo 'before'.'<br/>';
        return $next($request); //這裡才處理 request
    }
}
```

```
**After Middleware**

<?php

namespace App\Http\Middleware;

use Closure;

class AfterMiddleware
{
    public function handle($request, Closure $next)
    {
        $response = $next($request); //先處理 request （next 本身是閉包，會先處理 request)
        // Perform action			 //這裡才執行任務
        echo '</br>'.'after';
        return $response;
    }
}
```

## 中间件参数
中间件还可以接收额外的自定义参数，例如，如果应用需要在执行给定动作之前验证认证用户是否拥有指定的角色，可以创建一个 CheckRole 来接收角色名作为额外参数。

额外的中间件参数会在 $next 参数之后传入中间件：

```
namespace App\Http\Middleware;

use Closure;

class CheckRole
{
    public function handle($request, Closure $next, $role)
    {
        if (! $request->user()->hasRole($role)) {
            // Redirect...
        }

        return $next($request);
    }

}

Route::put('post/{id}', function ($id) {
    //
})->middleware('role:editor');
```
定義路由時，如需分配帶參數的中介層可通過一個 : 來隔開中介層名稱和參數。如有多個參數就使用逗號分隔：

## 特定路由移除 middware
當中介層已被分配給某個路由群組，但你需要將某個特定路由從這個中介層被排除掉，這時你就需要用到 withoutMiddleware() :

```
use App\Http\Middleware\EnsureTokenIsValid;

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

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

withoutMiddleware() 只能移除 route 中介層而不能移除全域中介層

## 排序中介層
極少情況下，你可能需要中介層以特定的順序來執行，但是當它們被分配到路由時，你無法控制它們的順序。在這種情況下，可以利用 app/Http/Kernel.php 檔案中的 $middlewarePriority 屬性來指定中介層的優先級，越前面的中介層會先被執行。這個屬性預設可能不在 HTTP內核裡頭，你可以複製這裡的預設內容如下：

```
/**
 * The priority-sorted list of middleware.
 *
 * This forces non-global middleware to always be in the given order.
 *
 * @var array
 */
protected $middlewarePriority = [
    \Illuminate\Cookie\Middleware\EncryptCookies::class,
    \Illuminate\Session\Middleware\StartSession::class,
    \Illuminate\View\Middleware\ShareErrorsFromSession::class,
    \Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests::class,
    \Illuminate\Routing\Middleware\ThrottleRequests::class,
    \Illuminate\Session\Middleware\AuthenticateSession::class,
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
    \Illuminate\Auth\Middleware\Authorize::class,
];
```

## 進階用法
```
$guard = Config::get('twjoinadmin.guard');                                       //admin guard
$authMiddleware = sprintf('%s:%s', Authenticate::class, $guard);                 //admin authentication middleware
$permissionMiddleware = sprintf('%s:%s', PermissionMiddleware::class, $guard);   //admin permission middleware(database)
$accountSuspendedMiddleware = sprintf('%s:%s', AccountSuspended::class, $guard); //admin user account suspended middleware
$ensureEmailIsVerifiedMiddleware = sprintf('%s:%s', EnsureEmailIsVerified::class, AdminPanel::routeName('verification.notice'));
$checkUserStatusMiddlewares = [$accountSuspendedMiddleware, $ensureEmailIsVerifiedMiddleware];
$namespace = '\App\Http\Controllers\Admin';

//no auth route
Route::get('login', [LoginController::class, 'showLoginForm'])->name('login');
Route::post('login', [LoginController::class, 'login']);
Route::post('logout', [LoginController::class, 'logout'])->name('logout');
Route::get('email/verify', [VerificationController::class, 'show'])->name('verification.notice');
Route::get('email/verify/{id}/{hash}', [VerificationController::class, 'verify'])->name('verification.verify');
Route::post('email/resend', [VerificationController::class, 'resend'])->name('verification.resend');

//auth route
Route::middleware([
        $authMiddleware,
        $permissionMiddleware,
    ])->group(
```
這樣不用去routeService註冊

因為那邊只是讓你middware有別名

另外參數用spinft去用入




###### tags: `Laravel`