laravel middleware

世有因果知因求果發表於2016-12-26

當你使用larvel建立一個相對比較複雜的web網站時,往往你的routes檔案就會變得很龐大。一般來說在開始網站編碼之前,最好做一個整體規劃,把這些route邏輯上劃分為不同的group,每一個group來定一個對應的middleware來控制這些route的訪問。比如admin,auth,public等邏輯大塊。通常每一個這樣的路由集都對應這不同的middleware,比如admin往往需要admin的middleware,必須具備管理員許可權的人才允許訪問。public則是所有登入使用者,甚至無需登入的任何使用者都可以訪問的routes. 另外,API group可能需要不同的auth middleware, 比如可能需要一個API相關的rate limiter或者其他的東西。

Laravel 5.2引入了一個middleware group的概念,實際上也就是使用一個名稱就可以應用一大堆的middleware。

如何建立一個admin的middleware group

我們可以在app/Http/Kernel.php檔案中定義middelware group.

Kernel類中定義了一個$middlewareGroups陣列屬性,我們就在這裡來定義新的middlewarep group。看看下面的程式碼就是laravel自帶的middlewaregroup:

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

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

從上面的例子我們就可以看到,這個陣列中的key(web,api)可以引用一個class類,或者一個route-specific middleware shortcut,比如throttle, 或者auth. 甚至web, api也可以被其他的key來引用

現在我們來這麼定義:

protected $middlewareGroups = [
    'web' => [...],
    'api' => [...],
    'admin' => [
        'web',
        'auth',
    ]
];

通過上面的程式碼,我們就定義了一個admin middlewaregroup,這個group使用了web(這又是另外一個middleware group),和一個auth(named route middleware).

你可能注意到了在web middlware group中定義的middleware在laravel 5.1中實際上是被應用到了每一個route上的,比如cookie,session,csrf等。但是從5.2開始對於這個做了比較大的改變:任何沒有被應用上web這個middleware group的route都將不具備cookie和session或者csrf的功能!

這也給了我們更多的靈活性:比如我們可以建立stateless的API而不用每次都應用那些middleware,也意味著效能的提高.

有必要指出的是:任何依賴於cookie或者session或者csrf的API將不能正常工作,如果他們被放在api 這個middlewaregroup下的話。所以,如果你有一些API是stateful的,那麼你需要對預設的api middlewaregroup做一些調整。

使用middlewaregroups

routes.php檔案中:

Route::get('/', function () {
    return view('welcome');
});

Route::group(['middleware' => ['web']], function () {
    //
});
Route::group(['middleware' => 'admin'], function () {
    Route::get('dashboard', function () {
        return view('dashboard');
    });
});

在5.2的後期版本,作者做了一下變更,在RouteServiceProvider中預設所有在routes.php檔案中定義的route都將被應用了'web'這個middlewaregroup!

 

相關文章