ThinkPHP中间件执行顺序由注册位置决定,全局改app/middleware.php数组顺序,路由级用appendMiddleware()避免前置插入,开启middleware_trace可验证真实执行链。

ThinkPHP中间件执行顺序错误,核心解决方式不是改配置项或加判断逻辑,而是直接调整注册位置——顺序由数组索引或链式调用次序决定,改错一位就可能让语言、鉴权、日志等关键功能失效。
全局中间件:改 app/middleware.php 数组顺序
打开 app/middleware.php,检查返回的数组元素顺序。ThinkPHP 6 按数组从左到右依次执行:
- Lang 中间件必须在 SessionInit 之后、LoadLangPack 之前,否则读不到 cookie('think_lang') 或语言包加载失败
- LoadLangPack 必须显式写入数组,不能省略;它负责真正载入 app/lang/zh-cn.php 文件
- AuthMiddleware 和权限校验类应连续靠前,不能被 Logger、Cors 等中间件隔开
- Cors 中间件需前置,确保响应头在业务逻辑前写入;若带 credentials,必须拦截 OPTIONS 请求
路由级中间件:用 appendMiddleware() 避免默认前置插入
路由定义中使用 ->middleware() 默认会把中间件插在最前面,容易打乱全局链。例如:
-
Route::get('admin')->middleware(Auth::class)→ Auth 会跑到 SessionInit 前面,导致 session 未初始化 - 想让它追加到末尾?改用
->appendMiddleware(Lang::class) - 多个中间件叠加时,
->middleware([A::class, B::class])中 A 先执行,B 后执行(请求阶段)
快速验证实际执行链
开启调试模式,在 config/app.php 中设 'middleware_trace' => true,发起请求后查看响应头 X-Middleware-Stack 字段,它会以逗号分隔列出真实执行的中间件类名。
立即学习“PHP免费学习笔记(深入)”;
- 如果 Lang 或 LoadLangPack 没出现在该字段里,说明它根本没进执行流程——不是配置错,是被跳过或顺序错位
- 该字段只显示最终执行的中间件,不显示被
return $next($request)提前终止的后续项 - 生产环境务必关闭
middleware_trace,避免泄露类结构
安全与多语言场景的典型顺序模板
一个兼顾语言切换和基础安全的常见顺序示例(app/middleware.php 返回数组):
\think\middleware\ForceHttpsMiddleware::class\think\middleware\SessionInit::class\think\middleware\Lang::class\think\middleware\LoadLangPack::class\think\middleware\AuthMiddleware::class\think\middleware\CheckPermission::class\think\middleware\Cors::class-
\think\middleware\Logger::class(靠后,需完整上下文)



















