本文包含如下小節,在閱讀以前建議大體閱讀官方文檔相關部分。php
中間件html
路由組node
在官方文檔上,這一部分是在路由的後面,但我想把它挪到前面來,這樣更爲合理。laravel
這是什麼呢?ajax
咱們知道,路由是一個過程,分析來自客戶端的請求按照路由規則分發至相應的處理邏輯。但有種狀況,打個比方:後臺。後臺不是全部人都能訪問的,咱們在正式的處理邏輯前,須要作一個驗證,好比驗證是否具備權限或者請求的數據是否合法。json
這時候,路由過程的一部分——中間件就上場了。數組
HTTP 中間件提供一個方便的機制來過濾進入應用程序的 HTTP 請求,例如,Laravel 默認包含了一箇中間件來檢驗用戶身份驗證,若是用戶沒有通過身份驗證,中間件會將用戶導向登陸頁面,然而,若是用戶經過身份驗證,中間件將會容許這個請求進一步繼續前進。app
上述內容來自中文版的laravel5文檔,裏面很好的說明了中間件的做用。在laravel5之前的版本,只有過濾器(路由篩選器),目的和如今 的中間件同樣都是在請求處處理邏輯之間的一箇中間過程,通常用做前置和後置的判斷、驗證。經過中間件咱們能夠在控制器裏專一其自己的邏輯,就比如一個後臺 的控制器,我只須要專一於顯示用戶列表或者文章列表、去處理添加的文章等等,而不須要關注訪問者是不是合法的後臺管理員,驗證權限的工做,應該交由中間 件。經過中間件驗證就會正常處理,不經過就會被重定向或者其餘操做。dom
Laravel默認已經內置了許多中間件,且默認開啓。能夠經過編輯app/Http/Kernel.php
來決定是否啓用這些中間件。本身開發的中間件也是在這裏進行註冊的哦。網站
app/Http/Kernel.php
中的 $middleware 數組是全局中間件,也就是說,任何一條路由都會被應用這些中間件,好比裏面的CSRF驗證中間件。有時候咱們不須要全局中間件,這時候能夠將某一箇中間件註冊至
app/Http/Kernel.php
文件中的$routeMiddleware數組,數組的鍵名是中間件的別名,鍵值是具體的中間件類,如'auth' => 'App\Http\Middleware\AuthMiddleware'。
具體如何在某一路由上使用特定的中間件咱們下文繼續。
咱們在app/Http/Kernel.php
文件中的$routeMiddleware數組註冊了一個獨立中間件,這一中間件可被單獨用綁定在一個路由和路由組上。在路由定義的時候能夠像這樣:
Route::get('admin/profile', ['middleware' => 'auth', function(){ //}]);
當咱們訪問http://yourdomain/admin/profile
的時候,首先會通過全局中間件,而後就是咱們在app/Http/Kernel.php
的$routeMiddleware數組中定義的名稱爲auth
的中間件。
說了這麼多關於如何定義,那麼中間件類裏面應該是什麼樣的呢?看過文檔的應該知道是這樣的(下面的代碼和文檔裏的有些區別哦):
<?phpnamespace App\Http\Middleware;use Closure;use Auth;class AuthMiddleware { /** * Run the request filter. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { // If the user is not logged in if (Auth::guest()) { if ($request->ajax()) { return response('Unauthorized!', 401); } else { return redirect()->guest('admin/login'); } } view()->share('loign', true); return $next($request); }}
上面這段代碼是已經寫好了的中間件,handle方法裏面的內容就是中間件實際的代碼。
咱們看得出第18~27行代碼大概是一個判斷用戶是否登錄的過程,若是沒有登陸,則判斷請求是不是ajax類型的,ajax類型的請求就返回一個表示「你丫的沒權限」的json數據(理解一下就行),若是是標準的請求就重定向至登錄界面。
若是在中間件中,經過了你的驗證、或者前置的操做邏輯,記得經過代碼return $next($request)
(上述例子中28行)將請求導向下一個中間件,若是後面沒有中間件,就會到的處理邏輯(好比控制器等)。
上述中間件是一個前置操做的中間件,什麼意思呢?就是在做用在實際處理邏輯前的中間件,就是一個前置中間件。相反,當一個實際處理邏輯運行完之後經過的中間件,就是一個後置中間件。
後置中間件結構以下:
<?phpnamespace App\Http\Middleware;class AfterMiddleware implements Middleware { public function handle($request, Closure $next) { $response = $next($request); // 具體的中間件邏輯代碼 return $response; }}
咱們看得出,區別在於多了個$response = $next($request)
,返回值也變了。很好理解,$next($request)
返回的值是整個請求通過無數具體處理邏輯後產生的最終響應,這個響應通常是一堆html代碼(渲染後的視圖),也多是一個json等等。咱們能夠在中間件裏面對這個響應作最後加工處理,最後返回處理完的結果。
這一塊官方文檔有着十分詳盡的描述,可是彷佛不太容易理解。先說說適用場景。
路由組羣每每適用於給某一類路由分組,給這個路由組分配的中間件、過濾器等,都會被運用到該組內的全部路由。
說白了,路由組就是簡化一部分路由定義過程的。好比,後臺的我都想經過地址http://yourdomain/admin/***
訪問,假如我有用戶(user)
、文章(article)
兩個模塊,他們的訪問都要通過一個驗證權限的中間件,我須要這樣定義路由:
Route::get('admin/user', ['middleware' => 'authority', function() { // blablabla...}]);Route::get('admin/article', ['middleware' => 'authority', function() { // blablabla...}]);
如今只有兩條路由,我多寫幾個admin,middleware沒啥的,但系統龐大之後,每一個都要單獨寫對應的中間件,容易出錯,不易管理。這時候,就應該使用路由組:
Route::group(['prefix' => 'admin', 'middleware' => 'authority'], function() { Route::get('user', function() { // blablabla... }); Route::get('article', function() { // blablabla... });});
同時,利用路由組,定義子域名變得十分容易:
Route::group(['domain' => 'bbs.yourdomain.com'], function() { Route::get('topic', function() { // blablabla... }); Route::get('node', function() { // blablabla... });});
子域名也能夠擁有通配符,以此實現更爲靈活的結構。好比我但願個人網站每個用戶都擁有本身的二級域名,相似於這樣:userA.yourdomain.com,userB.yourdomain.com。這時候能夠這樣寫:
Route::group(['domain' => '{username}.myapp.com'], function(){ Route::get('profile/{type}', function($username, $type) { // });});
能夠經過參數獲取域名上的通配符匹配的值。
除這些之外,路由組帶來的便利至關豐富,在這裏基本把路由組存在的意義說完了,其餘關於路由組的能夠移步至官方文檔瞭解。