Laravel中间件执行顺序由Kernel.php中$middleware、$middlewareGroups和$routeMiddleware数组的声明位置决定,遵循洋葱模型:全局中间件越靠前越“外”,路由组内按定义顺序执行,路由级中间件依注册位置而非调用顺序生效。

控制 Laravel 中间件执行顺序,核心不是写在路由里谁排前面,而是看它们在 app/Http/Kernel.php 里的注册位置和分组层级。Laravel 用的是「洋葱模型」:请求一层层往里走,响应一层层往外返,越靠外的中间件越早处理请求、越晚处理响应。
全局中间件顺序:数组从上到下 = 执行从外到内
在 $middleware 数组中,越靠前的类,实际越“靠外”——也就是请求进来时第一个碰到、响应出去时最后一个离开。比如:
-
TrustProxies::class放最顶上,确保后续中间件拿到的是真实 IP -
StartSession::class必须在Authenticate::class之前,否则登录态读不到 -
VerifyCsrfToken::class要在 session 启动之后,不然 token 验证会失败
调换它们在数组里的上下位置,就直接改变了执行先后。
路由组中间件:按 $middlewareGroups 里的顺序执行
像 web 或 api 这类中间件组,定义在 $middlewareGroups 数组里。组内中间件严格按数组顺序执行。例如:
-
'web' => [StartSession::class, ShareErrorsFromSession::class, Authenticate::class]表示先启 session,再共享错误,最后做登录校验 - 你在
routes/web.php里用Route::group(['middleware' => 'web'], ...),就会完整套用这个顺序
别指望在路由里写 ->middleware(['auth', 'throttle']) 就能改组内顺序——它只决定“用哪些”,不改变它们在组内的相对位置。
路由级中间件:顺序由 $routeMiddleware 声明位置决定
你自定义的中间件(如 EnsureUserHasProfile)注册在 $routeMiddleware 数组里。它的执行时机取决于它在该数组中的位置,而不是你在路由里写的顺序。
- 如果
'auth' => Authenticate::class写在第 3 行,而'ensure-user-has-profile' => EnsureUserHasProfile::class写在第 2 行,那后者永远比前者先执行 - 想让它在登录后才跑?就把它的定义行挪到
auth那一行的下面 - 同一个中间件别既放进
$middleware又放进$routeMiddleware,否则会重复执行
高级控制:$middlewarePriority 数组可强制重排
从 Laravel 5.6+ 开始,$middlewarePriority 数组能覆盖默认顺序,尤其适合解决“子域名识别必须在 auth 之前”这类强依赖场景。
- 它只影响全局中间件(
$middleware中的类)的相对顺序 - 把
Website::class放在Authenticate::class前面,就能确保多租户识别早于权限判断 - 注意:必须写完整命名空间;Laravel 9+ 默认已存在该数组,直接追加即可











