Laravel 中介軟體

huaweichenai發表於2018-11-21

Laravel 中介軟體提供了一種方便的機制來過濾進入應用的 HTTP 請求。例如,Laravel 內建了一箇中介軟體來驗證使用者的身份認證。如果使用者沒有透過身份認證,中介軟體會將使用者重定向到登入介面。但是,如果使用者被認證,中介軟體將允許該請求進一步進入該應用,所有中介軟體都位於 app/Http/Middleware 目錄下

一:建立中介軟體

使用 make:middleware 命令來建立新的中介軟體

php artisan make:middleware CheckAge  #CheckAge表示的是中介軟體檔名稱

該命令將會在 app/Http/Middleware 目錄內新建一個 CheckAge 類

在這個中介軟體裡,我們僅允許提供的引數 id 大於 200 的請求訪問該路由。否則,我們會將使用者重定向到 home

<?php
namespace App\Http\Middleware;
use Closure;
class CheckAge
{
    /**
     * 處理傳入的請求
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if ($request->id<= 200) {
            return redirect('home');
        }
        return $next($request);
    }
}

二:前置和後置中介軟體

中介軟體是在請求之前或之後執行取決於中介軟體本身

1:前置中介軟體

<?php
namespace App\Http\Middleware;
use Closure;
class BeforeMiddleware
{
    public function handle($request, Closure $next)
    {
        // 執行動作
        return $next($request);
    }
}

2:後置中介軟體

<?php
namespace App\Http\Middleware;
use Closure;
class AfterMiddleware
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);
        // 執行動作
        return $response;
    }
}

三:註冊中介軟體

1:註冊全域性中介軟體

如果你想讓中介軟體在你應用的每個 HTTP 請求期間執行,只需在 app/Http/Kernel.php 類中的 $middleware 屬性裡列出這個中介軟體類

protected $middleware = [
    \App\Http\Middleware\TrustProxies::class,
    \App\Http\Middleware\CheckForMaintenanceMode::class,
    \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
    \App\Http\Middleware\TrimStrings::class,
    \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];

2:為路由分配中介軟體

如果想為指定的路由配置中介軟體,首先應該在 app/Http/Kernel.php 檔案內為該中介軟體指定一個鍵。預設情況下,Kernel 類的 $routeMiddleware 屬性包含 Laravel 內建的中介軟體條目。要加入自定義的,只需把它附加到列表後併為其分配一個自定義鍵即可

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,
];

一旦在 Kernel 中定義了中介軟體,就可使用 middleware 方法將中介軟體分配給路由

Route::get('admin/profile', function () {
    //
})->middleware('auth');你還可以為路由分配多箇中介軟體
Route::get('/', function () {
    //
})->middleware('first', 'second');

分配中介軟體時,你還可以傳遞完整的類名

use App\Http\Middleware\CheckAge;

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

3:中介軟體組

有時你可能想用單一的鍵為幾個中介軟體分組,使其更容易分配到路由。可以使用 Kernel 類的 $middlewareGroups 屬性來實現

protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        // \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],

    'api' => [
        'throttle:60,1',
        'bindings',
    ],
];

可以使用與單箇中介軟體相同的語法將中介軟體組分配給路由和控制器操作

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

4:排序中介軟體

很少情況下,你可能需要中介軟體以特定的順序執行,但是當它們被分配到路由時,你無法控制它們的順序。在這種情況下,可以使用 app/Http/Kernel.php 檔案的 $middlewarePriority 屬性指定中介軟體優先順序

protected $middlewarePriority = [
    \Illuminate\Session\Middleware\StartSession::class,
    \Illuminate\View\Middleware\ShareErrorsFromSession::class,
    \App\Http\Middleware\Authenticate::class,
    \Illuminate\Routing\Middleware\ThrottleRequests::class,
    \Illuminate\Session\Middleware\AuthenticateSession::class,
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
    \Illuminate\Auth\Middleware\Authorize::class,
];

5:中介軟體引數

中介軟體也可以接受額外的引數。例如,如果應用需要在執行特定操作前驗證經過身份認證的使用者是否具備給定的「角色」,你可以新建一個 CheckRole 中介軟體,由它來接收「角色」名稱作為附加引數。

附加的中介軟體引數應該在 $next 引數之後被傳遞:

<?php
namespace App\Http\Middleware;
use Closure;
class CheckRole
{
    /**
     * 處理傳入的請求
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string  $role
     * @return mixed
     */
    public function handle($request, Closure $next, $role)
    {
        if (! $request->user()->hasRole($role)) {
            // 重定向...
        }
        return $next($request);
    }
}

定義路由時透過一個 : 來隔開中介軟體名稱和引數來指定中介軟體引數。多個引數就使用逗號分隔

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

6:Terminable 中介軟體

laravel 內建的「session」中介軟體會在響應傳送到瀏覽器之後將會話資料寫入儲存器中。如果你在中介軟體中定義一個 terminate 方法,則會在響應傳送到瀏覽器後自動呼叫

<?php
namespace Illuminate\Session\Middleware;
use Closure;
class StartSession
{
    public function handle($request, Closure $next)
    {
        return $next($request);
    }
    public function terminate($request, $response)
    {
        // Store the session data...
    }
}

terminate 方法應該同時接收和響應。一旦定義了這個中介軟體,你應該將它新增到路由列表或 app/Http/Kernel.php 檔案的全域性中介軟體中

在你的中介軟體上呼叫 terminate 呼叫時,Laravel 會從 服務容器 中解析出一個新的中介軟體例項。如果要在呼叫 handle 和 terminate 方法時使用同一個中介軟體例項,就使用容器的 singleton 方法向容器註冊中介軟體

相關文章