中间件注册顺序决定执行顺序:kernel.php中$middleware和$middlewaregroups数组顺序严格控制入栈(上到下)与出栈(下到上)流程,路由级middleware仅追加至组后,不可插队;$next($request)位置决定前置/后置逻辑,漏return将导致白屏。

中间件注册顺序决定执行顺序
在 Laravel 中,app/Http/Kernel.php 里定义的中间件数组顺序,直接对应请求进入和响应返回时的调用顺序。不是“谁先写进路由就先执行”,而是全局注册顺序优先级最高。
-
$middleware数组里的中间件(如TrustProxies、ValidatePostSize)会应用于所有请求,从上到下入栈,再从下到上出栈 -
$middlewareGroups['web']或['api']中的顺序同样严格生效;比如把EncryptCookies放在StartSession后面,会导致 session 无法解密 cookie - 路由中用
->middleware([...])追加的中间件,是“追加”到该路由所属中间件组已有的顺序之后,不是覆盖或插入中间
路由级中间件顺序不能“插队”,只能追加
你不能在 Route::get('/foo', ...)->middleware(['auth', 'log']) 中靠调整数组顺序来改变 auth 和 log 相对于 web 组内中间件的位置——它们始终排在整个 web 组之后。
- 想让某个中间件比
StartSession更早运行?必须把它移到$middlewareGroups['web']数组靠前位置,而不是塞进路由 -
->middleware(['throttle:api'])加在 API 路由上,实际执行时机在$middlewareGroups['api']全部跑完之后 - 如果需要精细控制(比如某接口要跳过
VerifyCsrfToken),得用except配置,而不是靠顺序绕过
中间件内部 $next() 调用位置影响逻辑流向
中间件函数体里 $next($request) 的位置,决定了它是“前置”还是“后置”行为——这和注册顺序无关,但常被误认为是顺序问题。
- 放在开头:先执行后续逻辑,再执行本中间件剩余代码(适合日志、计时、响应处理)
- 放在末尾:先执行本中间件逻辑,再放行(适合权限校验、请求改写)
- 漏掉
return $next($request)会导致请求中断且无报错,页面白屏或返回空响应 - 异步中间件(如含
await)需确保返回 Promise/Response,否则 Laravel 会当作同步流程处理并卡住
中间件类名重复或别名冲突会导致顺序失效
如果你在 Kernel.php 中同时写了 App\Http\Middleware\CheckAge::class 和 'check.age' 别名,并在路由中混用,Laravel 会去重——只保留第一个注册的,后面那个根本不会执行。
- 检查
dd($this->app['router']->getMiddleware())可看到最终生效的中间件列表,确认是否被意外过滤 - 别名命名避免和框架内置中间件重名(如自定义
throttle但没加前缀,可能被ThrottleRequests覆盖) - 使用
php artisan route:list --middleware查看每个路由实际绑定的中间件及其顺序,比读代码更直观
中间件顺序真正难调试的地方,往往不在注册位置,而在多个中间件之间共享状态(比如修改了 $request 属性但没 clone,下游中间件读到的是已被污染的对象)。这种问题不会报错,只会让行为变得不可预测。










