1. 程式人生 > >Laravel 學習筆記——路由(中介軟體與路由組)

Laravel 學習筆記——路由(中介軟體與路由組)

上一部分講述了laravel路由的基本用法,現在我們要了解更多路由上的內容。

本文包含以下小節,在閱讀之前建議大致閱讀官方文件相關部分。

  • 中介軟體
  • 路由組

中介軟體

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

這是什麼呢?

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

這時候,路由過程的一部分——中介軟體就上場了。

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

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

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的中介軟體。

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

<?php
namespace 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行)將請求導向下一個中介軟體,如果後面沒有中介軟體,就會到的處理邏輯(比如控制器等)。

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

後置中介軟體結構如下:

<?php
namespace 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)
    {
        //
    });
});

可以通過引數獲取域名上的萬用字元匹配的值。

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