中间件定义
中间件主要用于拦截或者过滤 http 请求,并进行必要的业务处理。
可以通过 php think make:middleware MyMiddleware
来创建,创建的中间件位置在 application/http/middleware
文件夹下
中间件的结构
<?php
namespace app\http\middleware;
class Check
{
public function handle($request, \Closure $next)
{
if ($request->param('name') === 'think') {
return redirect('/think');
}
return $next($request);
}
}
中间件的入口执行方法必须是 handle 方法,而且第一个参数是 Request 对象,第二个参数是一个闭包,在一些情况下允许有第三个参数
中间件的注册
中间件的位置在 application/http/middleware
文件夹下,我们可以在路由、应用目录、模块目录和控制器中注册使用中间件
路由中间件
在路由中直接注册中间件:
Route::get('hello/:name', 'index/hello')->middleware('Check'); //Check为上面 中间件的结构 中的例子的中间件类名
支持多个中间件:
Route::get('hello/:name', 'index/hello')->middleware(['Check','Auth']);
此外,在应用配置文件目录(即 config 文件夹)下的 middleware.php 文件中可以设置中间件的别名:
return [
'check' => app\http\middleware\Check::class,
'auth' => app\http\middleware\Auth::class,
];
然后在路由中就可以这样使用中间件了:
Route::get('hello/:name', 'index/hello')->middleware('check');
Route::get('hello/:name', 'index/hello')->middleware(['check','auth']);
在新版本中,别名还可以定义一组中间件:
return [
'check' => [
app\http\middleware\Check::class,
app\http\middleware\Auth::class,
]
];
这样可以实现使用一个别名,注册多个中间件
应用目录中间件(全局中间件)
在 application 目录下定义 middleware.php ,为应用目录下所有的控制器方法注册中间件:
<?php
return [
\app\http\middleware\Auth::class,
'Check',
];
模块中间件
在 index 模块下定义 middleware.php ,为当前模块下的所有控制器方法注册中间件:
return [
app\http\middleware\Auth::class,
'Check',
];
控制器中间件
控制器继承系统的 think\Controller
类,在控制器中定义 protected 属性的 middleware ,如下,当前控制器方法就会调用相应的中间件:
<?php
namespace app\index\controller;
use think\Controller;
class Index extends Controller
{
protected $middleware = ['Auth','check'];//可以使用别名或者中间件类名
public function index()
{
return 'index';
}
public function hello()
{
return 'hello';
}
}
同时在控制器中,对中间件配置 except
或者 only
属性,可以控制中间件是否生效:
<?php
namespace app\index\controller;
use think\Controller;
class Index extends Controller
{
protected $middleware = [
'Auth' => ['except' => ['hello'] ], //在 hello 方法中不生效
'check' => ['only' => ['hello'] ], //只有在 hello 方法中才生效
];
public function index()
{
return 'index';
}
public function hello($name = 'ThinkPHP5')
{
return 'hello' . $name;
}
}
中间件额外传参
路由中间件
传参的几种方式:
Route::get('hello/:name', 'index/hello')->middleware('Check:value');//只能使用中间件类名,无法使用别名
Route::get('hello/:name', 'index/hello')->middleware(Check::class,'value');
Route::get('hello/:name', 'index/hello')->middleware('Check','value');
Route::get('hello/:name', 'index/hello')->middleware('check','value');
Route::get('hello/:name', 'index/hello')->middleware([Check::class, 'auth'], 'value');//两个中间件传同样的参数,可以使用别名或者中间件类名
Route::get('hello/:name', 'index/hello')->middleware(['Check:value1', 'Auth:value2']);//两个中间件传不同的参数,不可以使用别名
在 Check 中间件中的 handle 方法中,就可以使用第三个参数来接收额外的参数 value 了。