中间件注册后不生效需检查注册位置:全局中间件放$middleware数组,分组中间件加到$middlewaregroups对应组,单路由用->middleware()绑定;顺序错误、命名空间缺失、session依赖时机不当等均会导致失效。

中间件注册后不生效?检查 app/http/Kernel.php 的注册位置
中间件必须在正确的位置注册,否则请求根本不会经过它。全局中间件写在 $middleware 数组里,会作用于所有请求;分组中间件(比如 web 或 api)得加到 $middlewareGroups 对应的数组中;而单个路由要用的,得用 ->middleware() 显式绑定。
-
$middleware里的中间件顺序敏感,靠前的先执行,比如TrustProxies必须在StartSession前,否则 session 读不到代理头 - 别把需要 session 的中间件(如
Authenticate)误塞进$middleware全局数组——API 路由没 session,会直接报Session store not set on request - 自定义中间件类名要带完整命名空间,比如
AppHttpMiddlewareCheckAge,漏写AppHttpMiddleware会导致类找不到
怎么给路由加中间件?middleware() 方法的三种写法
路由绑定中间件不是只有 ->middleware('auth') 这一种写法,不同场景得选对方式,不然容易漏掉参数或混淆作用域。
- 单个中间件:
Route::get('/profile', [ProfileController::class, 'show'])->middleware('auth') - 多个中间件:传数组,顺序即执行顺序,
->middleware(['auth', 'throttle:60,1']) - 带参数的中间件:用冒号分隔,
->middleware('role:admin,editor'),对应中间件handle($request, $next, ...$roles)中的$roles - 注意:控制器构造函数里调用
$this->middleware()是无效的——laravel 不支持构造时绑定,只能在路由定义或控制器方法上用
中间件里怎么中断请求?别只记得 return $next($request)
中间件的核心逻辑是“放行”或“拦截”,但很多人只写放行路径,忘了返回响应就等于让请求悬空,最终可能触发 500 或超时。
- 想拦截并跳转:用
return redirect()->route('login')或return response('Forbidden', 403) - 想终止并抛异常:用
throw new HttpResponseException(response(...)),避免后续中间件继续执行 - 别写
redirect()->route(...)->send()——send()会直接输出响应并终止 PHP,Laravel 的响应生命周期就被破坏了,日志、事件、终止器全失效 - 异步中间件(如队列任务前置检查)不能依赖
$request的 body 内容,因为 Laravel 默认不解析 json body 到$request->all(),需手动调用$request->json()->all()
为什么中间件里拿不到 $request->user()?session 和 auth 的加载时机问题
$request->user() 不是中间件一进来就有,它依赖 StartSession 和 Authenticate 这两个中间件的先后顺序。如果自定义中间件放在它们前面,user() 就是 NULL。
- 查
app/Http/Kernel.php里$middlewareGroups['web']的顺序:确保你的中间件在Authenticate之后(比如加在它下面),而不是塞到最顶上 - API 路由默认不走
web组,所以auth:api中间件用的是 Token 认证,$request->user()取的是ApiToken模型,不是User,类型不一致容易引发模型方法调用失败 - 测试时用
php artisan tinker模拟请求,别只靠浏览器刷新——session 状态可能被缓存,导致你以为中间件没跑
中间件链像流水线,每个环节都依赖前一个的输出。顺序错一点,$request 就少点东西,$next($request) 就可能崩在看不见的地方。