中间件注册不生效需检查注册位置:$middleware为全局中间件,$middlewareGroups为分组中间件(如api),须显式绑定路由;handle()中必须调用return $next($request)否则请求中断。

中间件注册后不生效?检查 $middleware 和 $middlewareGroups 的位置
中间件写好了,但请求压根没进到你的逻辑里——大概率是注册位置错了。Laravel 会按注册顺序执行中间件,而不同数组用途完全不同:$middleware 是全局中间件(所有请求都走),$middlewareGroups 是分组中间件(比如 web 或 api),必须显式绑定到路由才生效。
- 想让中间件只对 API 路由起作用?别往
$middleware里塞,加到$middlewareGroups['api']里,再在路由定义时用->middleware('api') - 自定义中间件类没被自动发现?确保它已通过
php artisan make:middleware CheckToken创建,且命名空间正确(默认在App\Http\Middleware) - 中间件内用了
dd()却没输出?可能是被前置中间件(比如StartSession)拦截了,换用日志或浏览器 Network 面板确认是否真被调用
handle() 里忘记调用 $next($request) 就等于中断请求
这是最常踩的坑:中间件函数写了逻辑,却漏掉最后一句 return $next($request);。结果就是请求卡死,浏览器一直转圈,或者返回空响应,连 500 错误都不报。
- 所有中间件
handle()方法都必须有且仅有一个return,要么放行(return $next($request);),要么提前终止(如return response()->json(..., 403);) - 别在中间件里写
exit或die—— Laravel 的异常处理、日志、响应格式全被绕过了 - 调试时临时加
Log::info('in middleware');比dd()更安全,避免阻断流程
过滤非法请求:用 abort_if() + 请求属性比手写 if-else 更稳
想拦掉 IP 不在白名单的请求?或拒绝非 POST 请求?直接操作 $request 对象比解析原始 URL 或 $_SERVER 变量更可靠,也兼容 Laravel 的测试模拟机制。
- 判断方法:
if ($request->method() !== 'POST') abort(405);或更简洁的abort_if($request->method() !== 'POST', 405); - 检查参数是否存在:
abort_if(!$request->has('token'), 400, 'Missing token');,比empty($request->token)更准(能区分 null / '' / 0) - IP 过滤慎用
$request->ip():反向代理下可能拿到的是 Nginx 的内网地址,得配好TRUSTED_PROXIES环境变量,否则永远拦不住真实用户
中间件传参只能靠构造函数,不能靠路由参数或闭包传参
你不能像控制器那样在路由里写 middleware(CheckRole::class . ':admin') 并指望中间件自动接收字符串参数——Laravel 不支持这种语法糖。所有参数必须在构造函数中注入,或通过服务容器绑定预设值。
- 需要动态角色名?改用中间件别名 + 参数绑定:在
app/Http/Kernel.php的$middlewareAliases里加'role' => \App\Http\Middleware\CheckRole::class,然后路由中写->middleware('role:admin') - 对应中间件类需实现
handle($request, Closure $next, ...$roles),参数会自动解包为数组 - 别在
handle()里做耗时操作(比如查数据库验证权限),除非你确认这个中间件不会被高频调用;高频场景建议缓存或合并到认证中间件中
中间件不是万能胶,它没法替代模型验证或策略授权;一个请求经过七八层中间件后,出问题时定位链路容易晕。最麻烦的其实是中间件之间的依赖顺序——比如你要在 session 启动之后才能读 $request->session(),那它就必须排在 StartSession 后面。











