### 2019 年 6 月 9 日 發布
6.0中間件分為系統中間件和應用中間件,系統中間件為核心框架內置的中間件,應用中間件是在應用里面創建的中間件。
>[danger] 中間件的主要應用場景可以包括對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 'Before Middleware<br/>';
$response = $next($request);
echo 'After Middleware<br/>';
return $response;
}
}
```
>[danger] 中間件`handle`方法的返回值必須是一個`Response`對象。
然后在全局中間件定義中添加
```
return [
\app\middleware\Test::class,
];
```
假設我們要訪問的控制器方法為
```
<?php
namespace app\controller;
class Index
{
public function hello()
{
return 'Hello,ThinkPHP!<br/>';
}
}
```
訪問該操作方法的輸出為
```
Before Middleware
Hello,ThinkPHP!
After Middleware
```
你可以看出中間件的執行過程,從執行流程上可以分為前置中間件和后置中間件,當然,一個中間件可能同時有前置和后置行為,上面的Test中間件就是如此。 $next($request)之前的代碼屬于前置中間件范疇,之后的代碼則屬于后置中間件范疇。
## 應用中間件
如果是多應用模式的話,應用中間件就是在`app\應用名\middleware.php`中定義的中間件,只會在該應用下有效,定義格式和全局中間件一致。
## 路由中間件
路由中間件則表示僅在路由匹配之后才會執行某個中間件,在路由定義中使用`middleware`方法定義,例如:
```
Route::get('hello/:name','index/hello')
->middleware(\app\middleware\Hello::class);
```
可以給路由分組定義中間件
```
Route::group(function(){
Route::get('hello/:name','index/hello');
//...
})->middleware(\app\middleware\Hello::class);
```
如果要執行多個中間件,可以使用
```
Route::group(function(){
Route::get('hello/:name','index/hello');
//...
})->middleware([\app\middleware\Hello::class,\app\middleware\Check::class]);
```
對于經常要使用的中間件,我們可以定義一個別名,在`config\middleware.php`配置文件中,設置
```
return [
'hello' => \app\middleware\Hello::class,
'check' => \app\middleware\Check::class,
];
```
路由定義可以改為:
```
Route::group(function(){
Route::get('hello/:name','index/hello');
//...
})->middleware(['hello','check']);
```
支持給一組中間件定義別名
```
return [
'test' => [\app\middleware\Hello::class,\app\middleware\Check::class],
];
```
路由定義可以改為
```
Route::group(function(){
Route::get('hello/:name','index/hello');
//...
})->middleware('test');
```
中間件支持傳入一個參數,中間件定義如下
```
<?php
namespace app\middleware;
class Hello
{
public function handle($request, \Closure $next, string $name = '')
{
echo 'Hello'. $name . '<br/>';
return $next($request);
}
}
```
可以在路由中間件的第二個參數傳入name參數
```
Route::get('hello/:name','index/hello')
->middleware('hello', 'middleware');
```
除了支持參數外,你可以在中間件的handle方法中使用依賴注入。
## 控制器中間件
控制器中間件僅當訪問某個控制器的時候生效
```
<?php
namespace app\controller;
class Hello
{
protected $middleware = ['hello','check'];
public function index()
{
return 'Hello,ThinkPHP!<br/>';
}
}
```
由于前面已經定義了中間件別名,所以這里直接使用別名定義,否則你必須使用完整的命名空間定義。
默認情況下,控制器中定義的中間件訪問控制器的任何操作方法都會執行,有時候并不希望所有的操作都需要執行中間件,有兩種方式來定義控制器中間件的執行過濾。
```
<?php
namespace app\controller;
class Index
{
protected $middleware = [
'hello' => ['only' => ['hello']],
'check' => ['except'=> ['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 app\middleware;
class Hello
{
public function handle($request, \Closure $next)
{
$request->hello = 'ThinkPHP';
return $next($request);
}
}
~~~
中間件向控制器傳參必須在前置中間件完成,后置中間件向控制器的傳參控制器無法接收。
然后在控制器的方法里面可以直接使用
~~~
public function index(Request $request)
{
return $request->hello; // ThinkPHP
}
~~~
- 值得升級到5.1的18個理由
- 5.1.7版本新特性
- JSON字段類型在ORM中的使用
- 文件下載響應對象
- 教你使用5.1的數組對象查詢
- 模型三大利器之一:搜索器
- 在ThinkPHP中使用Yaconf
- 掌握命令行的表格輸出
- 5.1.25查詢參數綁定的改進
- ThinkPHP安全規范指引
- 巧用數據集的排序功能實現統計排序
- think-orm ——基于5.1的獨立ORM庫
- think-template——基于ThinkPHP的獨立模板引擎
- ThinkPHP5.1.26版本發布——修正版本,包含安全更新
- ThinkPHP5.0和3.2再發安全更新
- 官宣:ThinkPHP發布首個LTS版本
- 你真的了解Db類和模型的正確使用姿勢么?
- 如何更有效的記錄和管理日志
- 模型三大利器之二:修改器
- ThinkPHP5.1.28版本發布——修正上一版本問題,改進關聯查詢
- 模型三大利器之三:獲取器
- API版本控制的幾種思路
- ThinkPHP5.2第一個Beta版本發布測試
- 讓你少犯錯的數據查詢基本原則
- ThinkPHP發布5.1.29版本——常規更新
- 這15個好習慣讓你更容易升級到5.2
- 如何有效提高ThinkPHP的應用性能
- 讓你提高開發效率的查詢技巧
- 模型關聯查詢不完全指南
- 5.2發布Beta2版本——統一和精簡大量用法
- ThinkPHP發布5.1.30版本——支持微秒時間字段寫入
- ThinkPHP的數據緩存使用
- ThinkPHP5.2安裝及入口文件
- ThinkPHP榮獲2018 年度最受歡迎中國開源開發框架第1名
- 5.1路由使用心得技巧
- ThinkPHP5.*版本發布安全更新
- ThinkPHP項目及代碼規范指北
- 5.2版本的設計規范指導
- ThinkPHP5.1.32版本發布——圣誕快樂
- 利用Trait特性給模型增加樂觀鎖功能
- 5.2數據庫和模型的變化(摘要)
- ThinkPHP模板引擎實現和常見問題
- ThinkPHP5.0.24版本發布——安全更新
- 不忘初心,方得始終——ThinkPHP十三周年報告
- ThinkPHP5+相關資源匯總
- 異步社區ThinkPHP周年慶專享優惠活動
- 5.2路由的調整和改進
- ThinkPHP發布5.1.33版本——包含安全更新
- ThinkPHP擴展開發指南
- ThinkPHP發布5.2Beta3版本
- ThinkPHP發布5.1.34版本——喜迎新年
- ThinkPHP發布5.2RC1版本
- ThinkPHP發布5.1.35版本——常規更新
- 5.2配置類的調整
- 5.2時間查詢的改進和優化
- 5.2RC版本升級不完全指導(僅供學習參考)
- ThinkPHP5.2版本正式變更為6.0版本
- ThinkPHP百度云云虛擬主機專享免費活動
- 事件系統以及查詢事件、模型事件的使用
- ThinkPHP6.0RC2版本發布——架構升級、精簡核心
- ThinkPHP5.1.36LTS版本發布——常規更新
- 新版Session和Cookie設計變化
- ThinkPHP5.1.37版本發布——常規更新
- ThinkPHP6.0RC3版本發布——細節完善,體驗優化
- 6.0中間件使用詳解
- Composer各大廠商鏡像地址
- ThinkPHP6.0發布計劃公告
- 「ThinkPHP開發者周刊」招募志愿者
- ThinkPHP6.0日志變化
- ThinkPHP5.1.38版本發布——常規更新
- ThinkPHP6.0RC4版本發布——ORM獨立,日志多通道支持
- ThinkORM2.0開發指南上線
- ThinkPHP6.0RC5版本發布——多應用模式獨立,中間件機制調整
- ThinkPHP6.0版本發布——程序員節福利
- ThinkPHP5.1.39LTS版本發布——常規更新
- ThinkPHP6.0.1版本發布——圣誕快樂!
- 回顧2019,展望2020!
- ThinkPHPV6.0.2版本發布——2020新春快樂!
- 周年福利系列:Swoole合作優惠
- 億速云成為ThinkPHPV6.0獨家贊助發布商??
- 新冠疫情工具和限免資源專題(保持更新中)
- 周年福利系列:創宇信用認證合作優惠
- 周年福利系列:碼云企業版限時10%優惠
- 周年福利系列:想天短說抵現優惠
- think-swoole直播:從零開始掌握swoole開發
- 周年福利系列:B2C開源電商ShopXO授權8折優惠
- 周年福利系列:LayuiAdmin 永久授權限時優惠
- ThinkPHP資源導航站上線——構建生態 服務未來
- ThinkPHP官方技術支持服務和應用服務市場上線公測
- ThinkPHP市場精選——推廣基本要素
- ThinkPHP市場精選——客服聊天專題
- ThinkPHPV6.0.3版本發布——端午安康
- ThinkPHP開發者扶持計劃
- 6.0.3版本關鍵更新及升級事項
- 「ThinkPHP開發者周刊」改版重啟
- ThinkPHP市場精選——企業建站專題
- ThinkPHP 提供統一API接口服務
- ThinkPHP市場精選——直播電商專題
- ThinkAPI服務SDK發布
- 官方服務市場啟用獨立子域名
- ThinkPHP市場精選——刷臉支付專題
- ThinkAPI推出會員服務計劃
- ThinkPHPV6.0.4版本發布——中秋國慶雙節快樂
- ThinkPHPV5.1.40版本發布——常規更新
- 1024程序員節福利走一波
- ThinkPHP V6.0.5版本發布——兼容Composer2.0
- 知識圖譜應用場景——源論技術沙龍
- ThinkPHP5.*版本改進Composer2.0的兼容
- 官方市場雙十一精選推薦
- 技術人做產品有機會么(文末送課程)
- 本周秒殺——古德云售后獲客營銷系統
- ThinkAPI服務更新——支持接口分組和PHP版本依賴調整
- PHP8新特性盤點
- PHP8新特性系列:構造器屬性提升使用及注意事項
- ThinkPHP2021新年寄語
- ThinkPHP V6.0.6&V5.1.41版本發布——兼容PHP8.0
- PHP如何更優雅地調用API接口
- ThinkPHP V6.0.7發布——修正版本
- ThinkAPI服務更新——IP白名單
- 最新版ThinkORM對于時間字段的調整
- ThinkAPI短信接口正式上線
- ThinkPHP V6.0.8版本發布——多環境變量配置支持
- 頂想云寫作服務開啟第一次公測
- ThinkSSL上線——官方SSL/TLS證書服務
- MDBootstrap國內用戶福利——ThinkPHP官方市場首發
- ThinkPHP V6.0.9版本發布——常規更新
- ThinkORM功能盤點——虛擬模型
- 全面支持主流GIT版本庫——云寫作服務第二次公測
- 云寫作服務私有化部署方案之:版本庫私有化
- 看云雙十一活動
- ThinkPHP V6.0.10LTS發布——兼容PHP8.1
- ThinkPHP V6.0.12發布——命令行兼容8.1
- 頂想云知識管理上線公測——構建企業文檔中心和知識庫
- 頂想云上線——助力生態數字化建設
- 618活動進行中——官方市場迎來一波更新
- 頂想云知識管理正式上線——看云文檔啟動遷移服務
- ThinkPHP V6.0.13發布——常規更新
- 頂想云網站助理服務上線——構建產品支持服務
- ThinkPHP發布6.1.0&6.0.14版本——安全更新
- ThinkPHP新版社區上線試運營
- ThinkAPI上架人臉核身接口——助力網站實名認證
- 辭舊迎新——舊版社區停止注冊及發帖
- ThinkPHP6.1.2版本發布——兼容PHP8.2