>[info]中間件主要用于攔截或過濾應用的`HTTP`請求,并進行必要的業務處理。在tp5.1.6引入
新版部分核心功能使用中間件處理,你可以靈活關閉。包括Session功能、請求緩存和多語言功能。
## **簡單案例**
### **步驟1:定義中間件**
>[danger]中間件的入口執行方法必須是`handle`方法,而且第一個參數是`Request`對象,第二個參數是一個閉包。
中間件`handle`方法的返回值必須是一個`Response`對象。
>[info]app\admin\middleware\Check.php
~~~
namespace app\admin\middleware;
class Check
{
public function handle($request, \Closure $next)
{
if ($request->param('name') == 'think') {
//向$request請求類添加新屬性 ,然后在你的`controller`中可以通過`$this->request->pay`獲取相關的值
$request->pay= 'WeChat';
//
return redirect('index/think');
}
return $next($request);
}
}
~~~
>[info]在某些需求下,可以使用第三個參數傳入額外的參數。
~~~
<?php
namespace app\admin\middleware;
class Check
{
public function handle($request, \Closure $next, $name)
{
if ($name == 'think') {
return redirect('index/think');
}
return $next($request);
}
}
~~~
### **步驟2:配置中間件**
>[info] 在app/middleware.php(全局中間件) 或者 app/admin/middleware.php(針對admin模塊)里添加如下代碼
~~~
return [
app\admin\middleware\Check::class,
];
~~~
# **結束調度**
中間件支持定義請求結束前的回調機制,你只需要在中間件類中添加`end`方法。
~~~
public function end(\think\Response $response)
{
// 回調行為
}
~~~
>[danger] 注意,在`end`方法里面不能有任何的響應輸出。因為回調觸發的時候請求響應輸出已經完成了。
# **前置/后置中間件**
>[info] 中間件是在請求具體的操作之前還是之后執行,完全取決于中間件的定義本身
## **前置行為的中間件**
~~~
<?php
namespace app\middleware;
class Before
{
public function handle($request, \Closure $next)
{
// 添加中間件執行代碼
return $next($request);
}
}
~~~
## **后置行為的中間件**
~~~
<?php
namespace app\middleware;
class After
{
public function handle($request, \Closure $next)
{
$response = $next($reque st);
// 添加中間件執行代碼
return $response;
}
}
~~~
中間件方法同樣也可以支持依賴注入。
來個比較實際的例子,我們需要判斷當前瀏覽器環境是在微信或支付寶
~~~
namespace app\middleware;
/**
* 訪問環境檢查,是否是微信或支付寶等
*/
class InAppCheck
{
public function handle($request, \Closure $next)
{
if (preg_match('~micromessenger~i', $request->header('user-agent'))) {
$request->InApp = 'WeChat';
} else if (preg_match('~alipay~i', $request->header('user-agent'))) {
$request->InApp = 'Alipay';
}
return $next($request);
}
}
~~~
然后在你的移動版的應用里添加一個`middleware.php`文件
例如:`/path/app/mobile/middleware.php`
~~~
return [
app\middleware\InAppCheck::class,
];
~~~
然后在你的`controller`中可以通過`request()->InApp`獲取相關的值
## **定義中間件別名**
可以直接在應用配置目錄下的`middleware.php`中先預定義中間件(其實就是增加別名標識),例如:
~~~
return [
'alias' => [
'auth' => app\middleware\Auth::class,
'check' => app\middleware\Check::class,
],
];
~~~
可以支持使用別名定義一組中間件,例如:
~~~
return [
'alias' => [
'check' => [
app\middleware\Auth::class,
app\middleware\Check::class,
],
],
];
~~~
# **注冊中間件**
新版的中間件分為全局中間件、應用中間件(多應用模式下有效)、路由中間件以及控制器中間件四個組。執行順序分別為:
>[info] 全局中間件->應用中間件->路由中間件->控制器中間件
## **路由中間件**
最常用的中間件注冊方式是注冊路由中間件
~~~
Route::rule('hello/:name','hello')
->middleware(\app\middleware\Auth::class);
~~~
支持注冊多個中間件
~~~
Route::rule('hello/:name','hello')
->middleware([\app\middleware\Auth::class, \app\middleware\Check::class]);
~~~
可以直接在應用配置目錄下的`middleware.php`中先預定義中間件(其實就是增加別名標識),例如:
~~~
return [
'auth' => app\middleware\Auth::class,
'check' => app\middleware\Check::class
];
~~~
然后直接在路由中使用中間件別名注冊
~~~
Route::rule('hello/:name','hello')
->middleware(['auth', 'check']);
~~~
可以支持使用別名定義一組中間件,例如:
~~~
return [
'check' => [
app\middleware\Auth::class,
app\middleware\Check::class
],
];
~~~
然后,直接使用下面的方式注冊中間件
~~~
Route::rule('hello/:name','hello')
->middleware('check');
~~~
支持對路由分組注冊中間件
~~~
Route::group('hello', function(){
Route::rule('hello/:name','hello');
})->middleware('auth');
~~~
支持對某個域名注冊中間件
~~~
Route::domain('admin', function(){
// 注冊域名下的路由規則
})->middleware('auth');
~~~
如果需要傳入額外參數給中間件,可以使用
~~~
Route::rule('hello/:name','hello')
->middleware('auth', 'admin');
~~~
如果需要定義多個中間件,使用數組方式
~~~
Route::rule('hello/:name','hello')
->middleware([Auth::class, 'Check']);
~~~
可以統一傳入同一個額外參數
~~~
Route::rule('hello/:name','hello')
->middleware(['auth', 'check'], 'admin');
~~~
或者分開多次調用,指定不同的參數
~~~
Route::rule('hello/:name','hello')
->middleware('auth', 'admin')
->middleware('hello', 'thinkphp');
~~~
如果你希望某個路由中間件是全局執行(不管路由是否匹配),可以不需要在路由里面定義,支持直接在路由配置文件中定義,例如在`config/route.php`配置文件中添加:
~~~
'middleware' => [
app\middleware\Auth::class,
app\middleware\Check::class,
],
~~~
這樣,所有該應用下的請求都會執行`Auth`和`Check`中間件。
## **使用閉包定義中間件**
你不一定要使用中間件類,在某些簡單的場合你可以使用閉包定義中間件,但閉包函數必須返回`Response`對象實例。
~~~
Route::group('hello', function(){
Route::rule('hello/:name','hello');
})->middleware(function($request,\Closure $next){
if ($request->param('name') == 'think') {
return redirect('index/think');
}
return $next($request);
});
~~~
## **全局中間件**
全局中間件在`app`目錄下面`middleware.php`文件中定義,使用下面的方式:
~~~
<?php
return [
\app\middleware\Auth::class,
'check',
'Hello',
];
~~~
中間件的注冊應該使用完整的類名,如果已經定義了中間件別名(或者分組)則可以直接使用。
全局中間件的執行順序就是定義順序。可以在定義全局中間件的時候傳入中間件參數,支持兩種方式傳入。
~~~
<?php
return [
[\app\http\middleware\Auth::class, 'admin'],
'Check',
['hello','thinkphp'],
];
~~~
上面的定義表示 給`Auth`中間件傳入`admin`參數,給`Hello`中間件傳入`thinkphp`參數。
## **應用中間件**
支持應用中間件定義,你可以直接在應用目錄下面增加`middleware.php`文件,定義方式和全局中間件定義一樣,只是只會在該應用下面生效。
## **控制器中間件**
支持為控制器定義中間件。只需要在控制器中定義`middleware`屬性,例如:
~~~
<?php
namespace app\controller;
class Index
{
protected $middleware = ['auth'];
public function index()
{
return 'index';
}
public function hello()
{
return 'hello';
}
}
~~~
當執行`index`控制器的時候就會調用`auth`中間件,一樣支持使用完整的命名空間定義。
如果需要設置控制器中間的生效操作,可以如下定義:
~~~
<?php
namespace app\controller;
class Index
{
protected $middleware = [
'auth' => ['except' => ['hello'] ],
'check' => ['only' => ['hello'] ],
];
public function index()
{
return 'index';
}
public function hello()
{
return 'hello';
}
}
~~~
## 中間件向控制器傳參
可以通過給請求對象賦值的方式傳參給控制器(或者其它地方),例如
~~~
<?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
}
~~~
# **內置中間件**
新版內置了幾個系統中間件,包括:
| 中間件類 | 描述 |
| --- | --- |
| think\\middleware\\AllowCrossDomain | 跨域請求支持 |
| think\\middleware\\CheckRequestCache | 請求緩存 |
| think\\middleware\\LoadLangPack | 多語言加載 |
| think\\middleware\\SessionInit | Session初始化 |
| ~~think\\middleware\\TraceDebug~~ | ~~頁面Trace支持~~ |
|think\middleware\FormTokenCheck|表單令牌|
這些內置中間件默認都沒有定義,你可以在應用的`middleware.php`文件中、路由或者控制器中定義這些中間件,如果不需要使用的話,取消定義即可。
- 空白目錄
- php語法結構
- 安裝與更新
- 開啟調試模式及代碼跟蹤器
- 架構
- 源碼分析
- 應用初始化
- 請求流程
- 中間件源碼分析
- 請求處理源碼分析
- Request源碼分析
- 模板編譯流程
- 路由與請求流程
- 容器
- 獲取目錄位置
- 入口文件
- 多應用模式及URL訪問
- 依賴注入與容器
- 容器屬性及方法
- Container
- App
- facade
- 中間件(middleware)
- 系統服務
- extend 擴展類庫
- 筆記
- 配置
- env配置定義及獲取
- 配置文件的配置獲取
- 單應用模式-(配置)文件目錄結構(默認)
- 多應用模式(配置)文件目錄結構(配置文件)
- 配置文件
- 應用配置:app.php
- 緩存配置: cache.php
- 數據庫配置:database.php
- 路由和URL配置:route.php
- Cookie配置:cookie.php
- Session配置:session.php
- 命令行配置:console.php
- 多語言配置:lang.php
- 日志配置:log.php
- 頁面Trace配置:trace.php
- 磁盤配置: filesystem.php
- 中間件配置:middleware.php
- 視圖配置:view.php
- 改成用yaconf配置
- 事件
- 例子:省略事件類的demo
- 例子2:完整事件類
- 例子3:事件訂閱,監聽多個事件
- 解析
- 路由
- 路由定義
- 路由地址
- 變量規則
- MISS路由
- URL生成
- 閉包支持
- 路由參數
- 路由中間件
- 路由分組
- 資源路由
- 注解路由
- 路由綁定
- 域名路由
- 路由緩存
- 跨域路由
- 控制器
- 控制器定義
- 空控制器、空操作
- 空模塊處理
- RESTFul資源控制器
- 控制器中間件
- 請求對象Request(url參數)
- 請求信息
- 獲取輸入變量($_POST、$_GET等)
- 請求類型的獲取與偽裝
- HTTP頭信息
- 偽靜態
- 參數綁定
- 請求緩存
- 響應對象Response
- 響應輸出
- 響應參數
- 重定向
- 文件下載
- 錯誤頁面的處理辦法
- 應用公共文件common.php
- 模型
- 模型定義及常規屬性
- 模型數據獲取與模型賦值
- 查詢
- 數據集
- 增加
- 修改
- 刪除
- 條件
- 查詢范圍scope
- 獲取器
- 修改器
- 搜索器
- 軟刪除
- 模型事件
- 關聯預載入
- 模型關聯
- 一對一關聯
- 一對多關聯
- 多對多關聯
- 自動時間戳
- 事務
- 數據庫
- 查詢構造器
- 查詢合集
- 子查詢
- 聚合查詢
- 時間查詢
- 視圖查詢(比join簡單)
- 獲取查詢參數
- 快捷方法
- 動態查詢
- 條件查詢
- 打印sql語句
- 增
- 刪
- 改
- 查
- 鏈式操作
- 查詢表達式
- 分頁查詢
- 原生查詢
- JSON字段
- 鏈接數據庫配置
- 分布式數據庫
- 查詢事件
- Db獲取器
- 事務操作
- 存儲過程
- Db數據集
- 數據庫驅動
- 視圖
- 模板
- 模板配置
- 模板位置
- 模板渲染
- 模板變量與賦值(assign)
- 模板輸出替換
- url生成
- 模板詳解
- 內置標簽
- 三元運算
- 變量輸出
- 函數輸出
- Request請求參數
- 模板注釋及原樣輸出
- 模板繼承
- 模板布局
- 原生PHP
- 模板引擎
- 視圖過濾
- 視圖驅動
- 驗證
- 驗證進階之最終版
- 錯誤和日志
- 異常處理
- 日志處理
- 調試
- 調試模式
- Trace調試
- SQL調試
- 變量調試
- 遠程調試
- 雜項
- 緩存
- Session
- Cookie
- 多語言
- 上傳
- 擴展說明
- N+1查詢
- TP類庫
- 擴展類庫
- 數據庫遷移工具
- Workerman
- think助手工具庫
- 驗證碼
- Swoole
- request
- app
- Response
- View
- Validate
- Config
- 命令行
- 助手函數
- 升級指導(功能的添加與刪除說明)
- siyucms
- 開始
- 添加頁面流程
- 列表頁加載流程
- 彈出框
- 基礎控制器
- 基礎模型
- 快速構建
- 表單form構建
- 表格table構建
- MakeBuilder
- 前端組件
- 日期組件
- layer 彈層組件
- Moment.js 日期處理插件
- siyucms模板布局
- 函數即其變量
- 前端頁面
- $.operate.方法
- $.modal.方法:彈出層
- $.common.方法:通用方法
- 被cms重寫的表格options
- 自定義模板
- 搜索框
- 自定義form表單
- 獲取表單搜索參數并組裝為url字符串