首頁  >  文章  >  php框架  >  一文了解ThinkPHP6.0之中間件

一文了解ThinkPHP6.0之中間件

爱喝马黛茶的安东尼
爱喝马黛茶的安东尼轉載
2019-12-16 13:22:207577瀏覽

一文了解ThinkPHP6.0之中間件

ThinkPHP6.0中介軟體分為系統中介軟體和應用中介軟體,系統中介軟體為核心框架內建的中間件,應用中間件是在應用裡面建立的中間件。

中間件的主要應用場景可以包括對HTTP請求的資料過濾、權限偵測、請求攔截等行為,使用中間件能夠讓控制器的定義更加簡單,許多額外的非核心業務流程的處理都可以交給中間件執行。

從中間件的使用範圍來看,可以分為全域中間件、應用中間件、控制器中間件和路由中間件。

全域中間件

全域中間件是在app\middleware.php中定義的中間件,預設沒有啟用任何中間件,但對支援的系統中間件做了註釋,你只需要取消註釋就可以使用對應的系統中間件,預設內容如下:

return [
    // 全局请求缓存
    // 'think\middleware\CheckRequestCache',
    // 多语言加载
    // 'think\middleware\LoadLangPack',
    // Session初始化
    // 'think\middleware\SessionInit',
    // 页面Trace调试
    // 'think\middleware\TraceDebug',
];

系統的部分功能交給中間件進行統一管理,包括全域請求快取、多語言的自動偵測與載入、Session初始化和頁面Trace調試,也就是說,預設安裝後的應用是不支援Session的,你必須全域開啟Session初始化中間件後Session才能生效。對於API應用程式來說,本身就不需要Session功能支援。

你可以在全域中間件定義檔中加入你的應用程式中間件,但盡可能確保系統中介軟體的優先執行,中間件定義需要使用完整的類別名,透過命令列指令可以快速創建一個應用中間件:

php think make:middleware Test

會自動產生一個app\middleware\Test中間件類,內容如下:

<?php
namespace app\middleware;
class Test
{
    public function handle($request, \Closure $next)
    {
    }
}

也支援透過指定完整命名空間的方式建立中間件類別

php think make:middleware app\middleware\Hello

我們新增一個測試輸出

<?php
namespace app\middleware;
class Test
{
    public function handle($request, \Closure $next)
    {
    echo &#39;Before Middleware<br/>&#39;;
    $response = $next($request);
    echo &#39;After Middleware<br/>&#39;;
    return $response;
    }
}

中間件handle方法的回傳值必須是一個Response物件。

然後在全域中間件定義中加入

return [
\app\middleware\Test::class,
];

假設我們要存取的控制器方法為

<?php
namespace app\controller;
class Index
{
    public function hello()
    {
    return &#39;Hello,ThinkPHP!<br/>&#39;;
    }
}

存取該操作方法的輸出為

Before Middleware
Hello,ThinkPHP!
After Middleware

你可以看出中間件的執行過程,從執行流程上可以分為前置中間件和後置中間件,當然,一個中間件可能同時有前置和後置行為,上面的Test中間件就是如此。 $next($request)之前的程式碼屬於前置中介軟體範疇,之後的程式碼則屬於後置中間件範疇。

應用中間件

如果是多應用模式的話,應用中間件就是在app\套用名稱\middleware.php中定義的中間件,只會在該應用下有效,定義格式和全域中間件一致。

路由中間件

路由中間件則表示僅在路由匹配之後才會執行某個中間件,在路由定義中使用middleware方法定義,例如:

Route::get(&#39;hello/:name&#39;,&#39;index/hello&#39;)
    ->middleware(\app\middleware\Hello::class);

可以為路由分組定義中間件

Route::group(function(){
Route::get(&#39;hello/:name&#39;,&#39;index/hello&#39;);
//...
})->middleware(\app\middleware\Hello::class);

如果要執行多個中間件,可以使用

Route::group(function(){
Route::get(&#39;hello/:name&#39;,&#39;index/hello&#39;);
//...
})->middleware([\app\middleware\Hello::class,\app\middleware\Check::class]);

對於經常要使用的中間件,我們可以定義一個別名,在config\middleware.php設定檔中,設定

return [
&#39;hello&#39;=>\app\middleware\Hello::class,
&#39;check&#39;=>\app\middleware\Check::class,
];

路由定義可以改為:

Route::group(function(){
Route::get(&#39;hello/:name&#39;,&#39;index/hello&#39;);
//...
})->middleware([&#39;hello&#39;,&#39;check&#39;]);

支援給一組中間件定義別名

return [
&#39;test&#39;=>[\app\middleware\Hello::class,\app\middleware\Check::class],
];

#路由定義可以改為

Route::group(function(){
Route::get(&#39;hello/:name&#39;,&#39;index/hello&#39;);
//...
})->middleware(&#39;test&#39;);

中間件支援傳入一個參數,中間件定義如下:

<?php
namespace app\middleware;
class Hello
{
    public function handle($request, \Closure $next, string $name = &#39;&#39;)
    {
    echo &#39;Hello&#39;. $name . &#39;<br/>&#39;;
    return $next($request);
    }
}

可以在路由中間件的第二個參數傳入name參數

Route::get(&#39;hello/:name&#39;,&#39;index/hello&#39;)
    ->middleware(&#39;hello&#39;, &#39;middleware&#39;);

除了支援參數外,你可以在中間件的handle方法中使用依賴注入。

控制器中間件

控制器中間件僅當存取某個控制器的時候生效

<?php
namespace app\controller;
class Hello
{
protected $middleware = [&#39;hello&#39;,&#39;check&#39;];
    public function index()
    {
    return &#39;Hello,ThinkPHP!<br/>&#39;;
    }
}

由於前面已經定義了中間件別名,所以這裡直接使用別名定義,否則你必須使用完整的命名空間定義。

預設情況下,控制器中定義的中間件存取控制器的任何操作方法都會執行,有時並不希望所有的操作都需要執行中間件,有兩種方式來定義控制器中間件的執行過濾。

<?php
namespace app\controller;
class Index
{
protected $middleware = [
&#39;hello&#39; => [&#39;only&#39;  => [&#39;hello&#39;]],
&#39;check&#39; => [&#39;except&#39;=> [&#39;hello&#39;]],
];
    public function hello()
    {
    return &#39;Hello,ThinkPHP!<br/>&#39;;
    }
    public function check()
    {
    return &#39;this action require check!<br/>&#39;;
    }    
}

hello中間件僅在執行Index控制器的hello操作的時候才會執行,而check中間件除了hello方法外,都會執行,具體效果你可以實際測試下。

中間件傳參

中間件和控制器之間傳參的方式有很多,一個簡單的方法是使用Request來進行傳參。

<?php
namespace app\middleware;
class Hello
{
    public function handle($request, \Closure $next)
    {
        $request->hello = &#39;ThinkPHP&#39;;
        
        return $next($request);
    }
}

中間件向控制器傳參必須在前置中間件完成,後置中間件向控制器的傳參控制器無法接收。

然後在控制器的方法裡面可以直接使用

public function index(Request $request)
{
return $request->hello; // ThinkPHP
}

眾多ThinkPHP教程視頻,盡在PHP中文網,歡迎在線學習!

本文轉自:https://www.php.cn/phpkj/thinkphp/

以上是一文了解ThinkPHP6.0之中間件的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:thinkphp.cn。如有侵權,請聯絡admin@php.cn刪除