Laravel中间件执行顺序由Kernel.php中$middleware、$middlewareGroups、$routeMiddleware三数组声明顺序决定,而非路由中书写顺序;需检查注册位置、避免重复注册、合理配置$middlewarePriority,并用日志调试实际执行流。

中间件执行顺序错乱,本质是注册位置没对齐,不是路由里写得靠前就真跑得早。Laravel 严格按 app/Http/Kernel.php 中三个数组的声明顺序来排执行栈——$middleware(全局)、$middlewareGroups(如 web/api 分组)、$routeMiddleware(路由级别别名),三者层级不同、顺序独立。
确认中间件注册位置是否正确
路由中写 ->middleware(['auth', 'log']) 只是“选人”,不决定谁先谁后。真正顺序由它们在 $routeMiddleware 数组里的定义顺序决定:
- 打开
app/Http/Kernel.php,找到protected $routeMiddleware = [ ... ] - 若你希望
auth先于log执行,就要确保'auth' => \App\Http\Middleware\Authenticate::class这一行写在'log' => \App\Http\Middleware\LogRequest::class上面 - 反之,若
log需要等用户登录后才记录操作,则必须把它放在auth之后
子域名校验类中间件必须抢在 auth 前执行
比如你有动态子域名路由 {website}.example.com,并写了 website 中间件做存在性检查(无效子域名直接 abort(404))。但若 auth 先触发,用户会被重定向到 /login,根本进不了你的校验逻辑。
这是因为 auth 属于「有状态中间件」,Laravel 内部通过 $middlewarePriority 强制提升其优先级。解决办法是把你自己的中间件也加入这个优先级列表,并放在 auth 相关类之前:
- 在
Kernel.php的$middlewarePriority数组中添加:\App\Http\Middleware\EnsureWebsiteExists::class - 确保它排在
\Illuminate\Auth\Middleware\Authenticate::class和\Illuminate\Session\Middleware\AuthenticateSession::class之前
避免中间件被重复注册或误塞进全局组
一个中间件如果既出现在 $middleware(全局)又出现在 $routeMiddleware(路由别名),Laravel 会去重,只执行第一个——通常是你在全局数组里写的那个,导致路由中指定失效。
- 检查有没有把本该只用于部分路由的中间件(如
throttle、cors)误加进了$middleware数组 - CORS 中间件尤其要注意:不能放全局组,否则连 favicon 请求都带跨域头;应只加在
$middlewareGroups['api']或['web']里,且位置要靠前(建议紧接EncryptCookies后) - 清除缓存验证改动:
php artisan config:clear && php artisan route:clear
调试执行顺序的实用方法
光看代码容易绕晕,可以用日志快速定位实际执行流:
- 在每个中间件
handle()开头加一句:info('→ Running: ' . static::class); - 再在结尾加:
info('← Done: ' . static::class); - 发起一次请求,查
storage/logs/laravel.log,就能看到真实调用顺序 - 注意:如果某中间件没出现在日志里,说明它根本没被注册,或者被前面某个中间件
return response()提前终止了











