從5.1.6+
版本開始,正式引入中間件的支持。
中間件主要用於攔截或過濾應用的HTTP請求,並進行必要的業務處理
官方手冊:https://www.kancloud.cn/manual/thinkphp5_1/564279
傳統式用戶過濾
通過繼承基類來達到權限的判斷。但在tp5.1.6之后可以使用中間件的方式更好
定義中間件
可以通過命令行指令快速生成中間件
#php think make:middleware 中間件的名稱
php think make:middleware Check
這個指令會 application/http/middleware
目錄下面生成一個Check
中間件。
例:
中間件的入口執行方法必須是handle
方法,而且第一個參數是Request
對象,第二個參數是一個閉包。
中間件
handle
方法的返回值必須是一個Response
對象。
中間件是在請求具體的操作之前還是之后執行,完全取決於中間件的定義本身。
前置中間件
下面是一個前置行為的中間件
<?php
namespace app\http\middleware;
class Before
{
public function handle($request, \Closure $next)
{
// 添加中間件執行代碼
return $next($request);
}
}
后置中間件
下面是一個后置行為的中間件
<?php
namespace app\http\middleware;
class After
{
public function handle($request, \Closure $next)
{
$response = $next($request);
// 添加中間件執行代碼
return $response;
}
}
注冊中間件
控制器注冊(path info)
V5.1.17+
版本開始,支持為控制器定義中間件。首先你的控制器需要繼承系統的think\Controller
類,然后在控制器中定義middleware
屬性,例如
控制器
<?php
namespace app\index\controller;
use app\index\validate\LoginValidate;
use think\captcha\Captcha;
use think\Controller;
use think\Request;
class Login extends Controller
{
//只適合pathinfo模式
protected $middleware = [
//中間件名稱
'CheckLogin'
];
//登陸界面
public function index(){
return '111';
//return view('index@login/index');
}
}
中間件
<?php
namespace app\http\middleware;
class CheckLogin
{
public function handle($request, \Closure $next)
{
echo "php 你好<br>";
return $next($request);
}
}
運行效果
路由中間件 middleware[常用]
最常用的中間件注冊方式是注冊路由中間件
Route::rule('hello/:name','hello')
->middleware('Auth');
或者使用完整的中間件類名
Route::rule('hello/:name','hello')
->middleware(app\http\middleware\Auth::class);
支持注冊多個中間件
Route::rule('hello/:name','hello')
->middleware(['Auth', 'Check']);
例:
路由中寫
Route::get('login', '@index/login/index')->name('login')->middleware('CheckLogin');
#或者 使用路由分組
Route::group(['middleware' => ['CheckLogin']],function (){
Route::get('login', '@index/login/index')->name('login');
});
運行結果
配置文件注冊(模塊和全局) middleware.php
此文件可以放在模塊下,就是對此模塊注冊此中間件,在application下面,就是全局中間件,說白了,就是所有的模塊講都有此中間件。
V5.1.7+
版本,你可以直接在應用配置目錄下的middleware.php
中先預定義中間件(其實就是增加別名標識),例如:
return [
'auth' => app\http\middleware\Auth::class,
'check' => app\http\middleware\Check::class
];
例:
<?php
return [
\app\http\middleware\CheckLogin::class
//或者
#\app\http\middleware\CheckLogin
];
運行效果
閉包中間件
你不一定要使用中間件類,在某些簡單的場合你可以使用閉包定義中間件,但閉包函數必須返回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);
});
中間件傳參
傳給控制器
請求對象賦值的方式
可以通過給請求對象賦值的方式傳參給控制器(或者其它地方),例如
<?php
namespace app\http\middleware;
class Hello
{
public function handle($request, \Closure $next)
{
$request->hello = 'ThinkPHP';
return $next($request);
}
}
注意,傳遞的變量名稱不要和
param
變量有沖突。
然后在控制器的方法里面可以直接使用
public function index(Request $request)
{
return $request->hello; // ThinkPHP
}
傳給中間件
配置文件 middleware.php
例:
配置文件 middleware.php
<?php
return [
[\app\http\middleware\CheckLogin::class, 'admin']
];
中間件
<?php
namespace app\http\middleware;
class CheckLogin
{
public function handle($request, \Closure $next, $name)
{
echo $name.'<br>';
echo "php 你好2222<br>";
return $next($request);
}
}
訪問控制器結果
自定義路由傳遞
Route::get('login', '@index/login/index')->name('login')->middleware('CheckLogin:guest');
#或者
Route::group(['middleware' => ['CheckLogin:guest' ]],function (){
Route::get('login', '@index/login/index')->name('login');
});
控制器傳遞
//pathinfo模式
protected $middleware = [
//中間件名稱
'CheckLogin:aaa'
];