laravel 學習筆記——路由(中間件與路由組)

本文包含以下小節,在閱讀之前建議大致閱讀官方文檔。

  • 中間件
  • 路由組

中間件

在官方文檔上,這一部分是在路由的後面,但我想把它挪到前面來,這樣更爲合理。

這是什麼呢?

我們知道,路由是一個過程,分析來自客戶端的請求按照路由規則分發至相應的處理邏輯。但有種情況,打個比方:後臺。後臺不是所有人都能訪問的,我們在正式的處理邏輯前,需要做一個驗證,比如驗證是否具有權限或者請求的數據是否合法。

這時候,路由過程的一部分——中間件就上場了。

HTTP 中間件提供一個方便的機制來過濾進入應用程序的 HTTP 請求,例如,Laravel 默認包含了一箇中間件來檢驗用戶身份驗證,如果用戶沒有經過身份驗證,中間件會將用戶導向登錄頁面,然而,如果用戶通過身份驗證,中間件將會允許這個請求進一步繼續前進。

上述內容來自中文版的 laravel 5 文檔,裏面很好的說明了中間件的作用。在 laravel 5 以前的版本,只有過濾器(路由篩選器),目的和現在的中間件一樣都是在請求到處理邏輯之間的一箇中間過程,一般用作前置和後置的判斷、驗證。通過中間件我們可以在控制器裏專注其本身的邏輯,就好比一個後臺的控制器,我只需要專注於顯示用戶列表或者文章列表、去處理添加的文章等等,而不需要關注訪問者是否是合法的後臺管理員,驗證權限的工作,應該交由中間件。通過中間件驗證就會正常處理,不通過就會被重定向或者其他操作。

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 數組註冊了一個獨立中間件,這一中間件可被單獨用綁定在一個路由和路由組上。在路由定義的時候可以像這樣:

  1. Route::get('admin/profile', ['middleware' => 'auth', function()
  2. {
  3. //
  4. }]);

當我們訪問 http://yourdomain/admin/profile 的時候,首先會經過全局中間件,然後就是我們在 app/Http/Kernel.php 的 $routeMiddleware 數組中定義的名稱爲 auth 的中間件。

說了這麼多關於如何定義,那麼中間件類裏面應該是什麼樣的呢?看過文檔的應該知道是這樣的(下面的代碼和文檔裏的有些區別哦):

  1. <?php
  2. namespace App\Http\Middleware;
  3.  
  4. use Closure;
  5. use Auth;
  6.  
  7. class AuthMiddleware {
  8.  
  9. /**
  10. * Run the request filter.
  11. *
  12. * @param \Illuminate\Http\Request $request
  13. * @param \Closure $next
  14. * @return mixed
  15. */
  16. public function handle($request, Closure $next)
  17. {
  18. // If the user is not logged in
  19. if (Auth::guest()) {
  20. if ($request->ajax()) {
  21. return response('Unauthorized!', 401);
  22. } else {
  23. return redirect()->guest('admin/login');
  24. }
  25. }
  26.  
  27. view()->share('loign', true);
  28. return $next($request);
  29. }
  30.  
  31. }

上面這段代碼是已經寫好了的中間件,handle 方法裏面的內容就是中間件實際的代碼。

我們看得出第 18~27 行代碼大概是一個判斷用戶是否登陸的過程,如果沒有登錄,則判斷請求是否是 ajax 類型的,ajax 類型的請求就返回一個表示“你丫的沒權限”的 json 數據(理解一下就行),如果是標準的請求就重定向至登陸界面。

如果在中間件中,通過了你的驗證、或者前置的操作邏輯,記得通過代碼 return $next($request)(上述例子中28行)將請求導向下一個中間件,如果後面沒有中間件,就會到的處理邏輯(比如控制器等)。

上述中間件是一個前置操作的中間件,什麼意思呢?就是在作用在實際處理邏輯前的中間件,就是一個前置中間件。相反,當一個實際處理邏輯運行完以後通過的中間件,就是一個後置中間件。

後置中間件結構如下:

  1. <?php
  2. namespace App\Http\Middleware;
  3.  
  4. class AfterMiddleware implements Middleware {
  5.  
  6. public function handle($request, Closure $next)
  7. {
  8. $response = $next($request);
  9.  
  10. // 具體的中間件邏輯代碼
  11.  
  12. return $response;
  13. }
  14. }

我們看得出,區別在於多了個 $response = $next($request),返回值也變了。很好理解,$next($request) 返回的值是整個請求經過無數具體處理邏輯後產生的最終響應,這個響應一般是一堆 html 代碼(渲染後的視圖),也可能是一個 json 等等。我們可以在中間件裏面對這個響應做最後加工處理,最後返回處理完的結果。

路由組羣

這一塊官方文檔有着十分詳盡的描述,但是似乎不太容易理解。先說說適用場景。

路由組羣往往適用於給某一類路由分組,給這個路由組分配的中間件、過濾器等,都會被運用到該組內的所有路由。

說白了,路由組就是簡化一部分路由定義過程的。比如,後臺的我都想通過地址http://yourdomain/admin/*** 訪問,假如我有 用戶(user)文章(article) 兩個模塊,他們的訪問都要經過一個驗證權限的中間件,我需要這樣定義路由:

  1. Route::get('admin/user', ['middleware' => 'authority', function() {
  2. // blablabla...
  3. }]);
  4.  
  5. Route::get('admin/article', ['middleware' => 'authority', function() {
  6. // blablabla...
  7. }]);

現在只有兩條路由,我多寫幾個 admin,middleware 沒啥的,但系統龐大以後,每個都要單獨寫對應的中間件,容易出錯,不易管理。這時候,就應該使用路由組:

  1. Route::group(['prefix' => 'admin', 'middleware' => 'authority'], function() {
  2. Route::get('user', function() {
  3. // blablabla...
  4. });
  5. Route::get('article', function() {
  6. // blablabla...
  7. });
  8. });

同時,利用路由組,定義子域名變得十分容易:

  1. Route::group(['domain' => 'bbs.yourdomain.com'], function() {
  2. Route::get('topic', function() {
  3. // blablabla...
  4. });
  5.  
  6. Route::get('node', function() {
  7. // blablabla...
  8. });
  9. });

子域名也可以擁有通配符,以此實現更爲靈活的結構。比如我希望我的網站每一個用戶都擁有自己的二級域名,類似於這樣:userA.yourdomain.com,userB.yourdomain.com。這時候可以這樣寫:

  1. Route::group(['domain' => '{username}.myapp.com'], function()
  2. {
  3. Route::get('profile/{type}', function($username, $type)
  4. {
  5. //
  6. });
  7. });

可以通過參數獲取域名上的通配符匹配的值。

除這些以外,路由組帶來的便利相當豐富,在這裏基本把路由組存在的意義說完了,其他關於路由組的可以移步至官方文檔瞭解。

原文:https://www.insp.top/article/learn-laravel-middleware-routegroup


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章