thinkphp 6.0 起废弃 app/middleware.php 全局数组配置,改用返回中间件类数组的 app/middleware.php 文件;局部中间件须通过路由 middleware() 方法或控制器 initialize() 中 $this->middleware->add() 注册,禁用 halt(),优先级由 priority 属性控制。

中间件配置文件位置变了,app/middleware.php 已废弃
ThinkPHP 6.0 起取消了全局数组式中间件配置文件,所有中间件注册必须通过 app/middleware.php(v5.x)迁移至 app/middleware.php 不再生效。现在统一由 app/middleware.php 替代 —— 等等,别急,这其实是常见误解:v6 实际上已移除该文件,中间件注册全部收口到 app/middleware.php?错。正确路径是 app/middleware.php 已彻底删除,改用 app/middleware.php?也不对。真相是:app/middleware.php 在 v6+ 中不存在,所有中间件绑定必须在 app/middleware.php?不,是 app/middleware.php 这个文件名根本没变,但内容结构完全不同 —— 它现在是一个返回中间件类数组的 PHP 文件,且仅用于全局中间件注册。
实操建议:
-
app/middleware.php(v6+)只负责定义全局中间件执行顺序,格式为[\App\Middleware\CheckAuth::class, \think\middleware\AllowCrossDomain::class] - 该文件不再支持键值对写法(如
'auth' => \App\Middleware\CheckAuth::class),否则会报Invalid middleware definition - 中间件类必须可实例化(不能是抽象类或接口),且构造函数参数需能被容器自动解析;含不可解析参数会触发
BindingResolutionException - 若使用闭包中间件,必须显式写成
function (\think\Request $request, \Closure $next) { ... },不能省略类型提示,否则运行时报TypeError
路由分组/控制器/方法级中间件怎么绑:用 middleware() 方法而非注解
v6.0 开始,@middleware 注解默认不启用,且即使开启也不推荐用于生产环境 —— 因为注解解析发生在请求时,有性能损耗,且 IDE 支持弱、调试困难。
实操建议:
- 局部中间件优先走路由定义:在
app/route/app.php中用->middleware()链式调用,例如:Route::get('api/user', 'Api/UserController@index')->middleware(\App\Middleware\JwtAuth::class); - 多个中间件可传数组:
->middleware([\App\Middleware\JwtAuth::class, \App\Middleware\RateLimit::class]) - 控制器级绑定应写在
initialize()方法里(非构造函数):protected function initialize() { $this->middleware->add(\App\Middleware\CheckScope::class); } - 注意:
$this->middleware是think\route\Rule的实例,不是容器对象;在控制器中调用add()仅对当前控制器有效,且必须在initialize()中执行,放__construct()里无效
中间件执行顺序不是“先全局后局部”,而是按注册时机+层级合并后重排
很多人以为全局中间件一定最先执行、路由中间件其次、控制器中间件最后 —— 错。TP6 的中间件调度器会把三者合并为一个扁平队列,再根据「注册优先级」和「中间件类的 priority 属性」重新排序。
实操建议:
- 中间件类可定义
protected $priority = 10;,数值越小越靠前;未定义则默认为0 - 全局中间件在
app/middleware.php中的书写顺序仅影响同优先级下的相对位置,不决定绝对先后 - 路由中间件的
priority默认为0,但可通过->middleware(\App\Middleware\X::class, ['priority' => -5])显式指定(注意:第二个参数是选项数组,不是中间件参数) - 若两个中间件
priority相同,且来自不同来源(比如一个全局、一个路由),则全局中间件排在前面 —— 这是唯一保留的“来源优先级”规则
halt() 和 return 在中间件中的行为差异极大
中间件里写 return $response 是标准做法,但有人习惯用 halt($msg) 或 exit,这会导致后续中间件、控制器、视图全部跳过,且响应头可能已发送,极易引发 headers already sent 错误。
实操建议:
- 中间件内禁止使用
halt()、die()、exit();必须提前终止流程时,应return response()->json(['code'=>401])->send(); die();?不对 —— 正确做法是return response()->json(['code'=>401]);,让框架接管输出 - 如果中间件需要跳过后续所有处理(包括控制器),直接
return response()->code(403)->withHeader('X-Skipped', 'true');即可,框架会自动中断 pipeline - 特别注意:
return $next($request)必须存在,否则请求链断裂;漏写会导致 500 错误且无日志(因为 pipeline 没有返回值) - 调试时可在中间件中加
Log::debug('middleware X executed');,但避免在return前写echo,否则污染响应体
halt() 和注解写法会静默失效或引发奇怪的 header 错误。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











