laravel中间件执行顺序由$middleware、$middlewaregroups和路由middleware()调用顺序决定,遵循数组索引的洋葱模型;全局中间件在最外层,路由级中间件优先级最高但会去重。

中间件没有全局“优先级”配置,顺序完全由 $middleware、$middlewareGroups 和路由定义时的 middleware() 调用顺序决定。
中间件执行顺序只取决于注册位置
Laravel 的中间件是按数组索引顺序逐个入栈再出栈(类似洋葱模型),不是靠权重或标签排序。Kernel 中三个关键数组决定了实际执行流:
-
$middleware:全局中间件,所有请求都走,排最前 -
$middlewareGroups:分组中间件(如web、api),仅在路由指定了对应组时才生效 - 路由闭包或控制器方法上显式调用的
middleware():追加在组之后,优先级最高(但注意:重复中间件会被去重,除非禁用自动去重)
例如,在 routes/web.php 中写:Route::get('/test', ...)->middleware(['auth', 'log.request']),则 log.request 一定在 auth 之后执行(前提是二者未被提前注册在 $middleware 中)。
如何确保某个中间件总在最外层或最内层
想让它最先执行(比如做请求劫持或日志起始标记),就把它塞进 $middleware 数组开头;想让它最后执行(比如响应后处理),就放在 $middlewareGroups['web'] 的末尾,或通过路由单独追加。
- 修改
app/Http/Kernel.php时,不要动EncryptCookies、StartSession等依赖前置状态的中间件位置——它们有隐式依赖链 - 自定义中间件若依赖 session 或认证状态,就不能放在
$middleware最前面,否则$request->user()会是 null - 如果需要动态控制顺序(比如某些路由跳过某中间件),用中间件参数或条件判断比硬编码顺序更可靠
中间件重复注册导致顺序错乱的典型表现
常见错误现象:AuthMiddleware 在响应里读不到用户,但请求里明明已登录;或者 CorsMiddleware 没生效,浏览器报跨域错误。
- 检查是否同时在
$middlewareGroups['api']和路由中写了->middleware('cors')—— Laravel 默认会去重,只执行一次,且以首次出现位置为准 - 用
php artisan route:list --middleware查看每条路由实际绑定的中间件列表和顺序,这是唯一可信依据 - 若必须强制多次执行同一中间件(极少见),需在
app/Http/Kernel.php中设置protected $middlewarePriority = [];并清空它(Laravel 5.5+ 默认启用去重)
不建议强行“改优先级”的场景
试图给中间件加注解、配置项或用事件监听来干预执行顺序,基本不可行且违背 Laravel 设计逻辑。
- 中间件不是服务容器绑定对象,不支持
bind()时指定 order -
boot()或register()阶段无法修改已加载的中间件数组顺序 - 真正需要精细控制流程的地方(如权限校验分支、多步骤预检),应该拆成多个专用中间件,并靠代码逻辑串联,而不是堆顺序
最易被忽略的一点:中间件类里的 handle() 方法返回值必须是 $next($request) 的结果,漏掉或写成 return response(...) 会直接中断后续中间件——这不是顺序问题,而是执行流被截断了。











