一文了解ThinkPHP6.0之中間件

一文了解ThinkPHP6.0之中間件

ThinkPHP6.0中間件分為系統中間件和應用中間件,系統中間件為核心框架內置的中間件,應用中間件是在應用里面創建的中間件。

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

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

全局中間件

立即學習PHP免費學習筆記(深入)”;

全局中間件是在appmiddleware.php中定義的中間件,默認沒有啟用任何中間件,但對支持的系統中間件做了注釋,你只需要取消注釋就可以使用相應的系統中間件,默認內容如下:

return?[ ????//?全局請求緩存 ????//?'thinkmiddlewareCheckRequestCache', ????//?多語言加載 ????//?'thinkmiddlewareLoadLangPack', ????//?Session初始化 ????//?'thinkmiddlewareSessionInit', ????//?頁面Trace調試 ????//?'thinkmiddlewareTraceDebug', ];

系統的部分功能交給中間件進行統一管理,包括全局請求緩存、多語言的自動檢測和加載、Session初始化和頁面Trace調試,也就是說,默認安裝后的應用是不支持Session的,你必須全局開啟Session初始化中間件后Session才能生效。對于API應用來說,本身就不需要Session功能支持。

你可以在全局中間件定義文件中添加你的應用中間件,但盡可能確保系統中間件的優先執行,中間件定義需要使用完整的類名,通過命令行指令可以快速創建一個應用中間件:

php?think?make:middleware?Test

會自動生成一個appmiddlewareTest中間件類,內容如下:

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

也支持通過指定完整命名空間的方式創建中間件類

php?think?make:middleware?appmiddlewareHello

我們添加一個測試輸出

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

中間件handle方法的返回值必須是一個Response對象。

然后在全局中間件定義中添加

return?[ appmiddlewareTest::class, ];

假設我們要訪問的控制器方法為

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

訪問該操作方法的輸出為

Before?Middleware Hello,ThinkPHP! After?Middleware

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

應用中間件

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

路由中間件

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

Route::get('hello/:name','index/hello') ????-&gt;middleware(appmiddlewareHello::class);

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

Route::group(function(){ Route::get('hello/:name','index/hello'); //... })-&gt;middleware(appmiddlewareHello::class);

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

Route::group(function(){ Route::get('hello/:name','index/hello'); //... })-&gt;middleware([appmiddlewareHello::class,appmiddlewareCheck::class]);

對于經常要使用的中間件,我們可以定義一個別名,在configmiddleware.php配置文件中,設置

return?[ 'hello'=&gt;appmiddlewareHello::class, 'check'=&gt;appmiddlewareCheck::class, ];

路由定義可以改為:

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

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

return?[ 'test'=&gt;[appmiddlewareHello::class,appmiddlewareCheck::class], ];

路由定義可以改為

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

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

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

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

Route::get('hello/:name','index/hello') ????-&gt;middleware('hello',?'middleware');

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

控制器中間件

控制器中間件僅當訪問某個控制器的時候生效

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

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

默認情況下,控制器中定義的中間件訪問控制器的任何操作方法都會執行,有時候并不希望所有的操作都需要執行中間件,有兩種方式來定義控制器中間件的執行過濾。

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

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

中間件傳參

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

<?php namespace appmiddleware; class Hello {     public function handle($request, Closure $next)     {         $request->hello?=?'ThinkPHP'; ???????? ????????return?$next($request); ????} }

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

然后在控制器的方法里面可以直接使用

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

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

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

? 版權聲明
THE END
喜歡就支持一下吧
點贊10 分享