中间件未执行常因注册时机或顺序错误:thinkphp中db等服务仅在app::initialize()后可用,过早注册会抛logicexception;x-middleware-stack仅记录实际进入handle的中间件;顺序由注册位置决定,非文件名或注解顺序。

中间件报错不能只看异常消息,得先确认它是否真的执行到了出问题那一步——很多 LogicException 其实是中间件根本没进执行链就被框架拦下了。
为什么中间件里调 Db::table() 直接抛 LogicException
不是语法错,是时机错。ThinkPHP 6 的中间件注册分两个阶段:容器初始化前(只能用基础类)和 App::initialize() 后(Db/Cache/Model 才可用)。你在 app/middleware.php 里直接写 \app\middleware\LogMiddleware::class,它就会在数据库配置加载前被实例化,Db::table() 调用时容器还没准备好,自然报 LogicException: The application must be in maintenance mode 或更隐晦的 Call to a member function on null。
- 删掉
app/middleware.php中对这类中间件的数组返回 - 改用
app/bootstrap.php或app/common.php动态注册:app()->middleware->add(\app\middleware\LogMiddleware::class, 'http') - 确保该行代码在
think\initializer\BootService执行之后、app()->bindTo('http', ...)之前
路由级中间件没生效,但 X-Middleware-Stack 里有它
头里有不代表真执行了。ThinkPHP 的 X-Middleware-Stack 只记录进入 handle 流程的中间件;一旦某个中间件里写了 if ($condition) return $next($request);,而 $next($request) 内部抛异常(比如下一个中间件构造失败),整个链就断了,后续中间件不会出现在头里,但你看到的“已注册”只是假象。
- 开启
middleware_trace => true(仅开发环境),检查响应头X-Middleware-Stack的实际内容 - 如果某中间件没出现,别急着调顺序,先在它的
handle()开头加日志:\think\facade\Log::info('LogMiddleware entered'); - 再查 runtime/log 下对应时间的日志,确认它是压根没进,还是进了但
$next($request)没返回
中间件顺序混乱,Auth 和 CheckRole 执行反了
ThinkPHP 不按文件名、不按类名、不按注解书写顺序排——只认注册顺序。全局看 app/middleware.php 数组索引,路由级默认前置插入(->middleware() 会插到最前),不是追加到末尾。
- 想让
RateLimit在Auth之后执行?别用->middleware(RateLimit::class),改用->appendMiddleware(RateLimit::class) - 控制器注解
@middleware和路由方法效果一致,同样受前置规则约束 - 混合使用时,最终顺序 = 路由级
appendMiddleware+ 全局app/middleware.php数组 + 路由级middleware(前置)
最容易被忽略的是:中间件里依赖服务(如 Db)却注册太早,错误发生在构造函数或属性注入阶段,连 handle() 都进不去,这时候看日志、看堆栈、看注册位置,比调试逻辑本身还重要。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











