Laravel怎么使用中间件_Laravel Middleware使用教程【解析】

2次阅读

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

Laravel怎么使用中间件_Laravel Middleware使用教程【解析】

中间件注册后不生效?检查 app/http/Kernel.php 的注册位置

中间件必须在正确的位置注册,否则请求根本不会经过它。全局中间件写在 $middleware 数组里,会作用于所有请求;分组中间件(比如 webapi)得加到 $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() 不是中间件一进来就有,它依赖 StartSessionAuthenticate 这两个中间件的先后顺序。如果自定义中间件放在它们前面,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) 就可能崩在看不见的地方。

text=ZqhQzanResources