前置中间件指handle方法中将$next($request)置于最后执行,用于权限校验等拦截逻辑;后置中间件则将$next($request)置于开头,处理已生成的$response,适用于日志、响应头等操作。

ThinkPHP 中间件本身没有“前置操作”这个独立概念,所谓“前置操作”实际就是指 handle 方法中把 $next($request) 放在最后执行的写法——也就是「前置中间件」。它不是额外功能,而是中间件的一种使用方式。
前置中间件 = $next($request) 写在最后
这是最常用、也最符合拦截逻辑的写法。所有权限校验、登录检查、请求改写都该放在这里。
- 请求还没进控制器,
$request->controller()和$request->action()在 ThinkPHP 6/8 中多数情况下返回空或不准确(取决于路由解析时机) - 一旦判断失败(比如没登录),直接
return json(['code' => 401]),后续流程彻底跳过,控制器代码不会执行 - 可以安全修改
$request对象(如注入用户信息:$request->user = $user),下游能拿到 - 错误示例:把
return $next($request)写在条件判断之前,会导致拦截失效
后置中间件 = $next($request) 写在开头,处理 $response
它本质是「响应阶段处理」,不是用来做拦截的,因为控制器和业务逻辑已经跑完了。
-
$request->controller()和$request->action()此时一定可读,适合记录日志、统计接口耗时、统一添加响应头 - 常见误用:拿它做权限拦截——即使
return redirect(),控制器里该写的文件、该查的库、该发的邮件,全已执行完毕 - 必须显式返回
$response,否则会报错:Return value of app\middleware\After::handle() must be an instance of think\Response - 如果中间件里需要读取响应内容(比如压缩或加密 body),得先调用
$response->getContent(),再用$response->withContent()替换
注册位置决定执行顺序,不决定前置/后置性质
中间件是前置还是后置,只看 handle 方法内部怎么写,跟注册方式(全局 / 路由 / 控制器)无关。但注册位置会影响它能否被触发。
立即学习“PHP免费学习笔记(深入)”;
- 全局中间件对所有请求生效,适合鉴权、跨域头;但别在里面做
redirect,容易误杀静态资源 - 路由中间件最精准,比如只给
admin/*加Auth中间件,命令是:php think make:middleware admin@Auth - 控制器中间件需在控制器类顶部加注解:
@middleware('CheckAuth'),注意命名空间要匹配 - 多个中间件串联时,前置中间件的「前置代码」按注册顺序从上到下执行,后置代码则倒序执行
真正容易被忽略的是:ThinkPHP 6.0+ 的路由解析在中间件管道中较晚才完成,所以依赖 $request->controller() 做判断的前置中间件,大概率拿不到值——要么改用 $request->rule() 或 $request->url() 匹配路径,要么把逻辑挪到后置阶段(如果业务允许控制器先执行)。



















