从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'
];