中间件没生效主要是注册位置或闭包写法错误:middleware()只接受字符串或数组,不可调用函数;全局中间件与路由组中间件需匹配使用;handle()必须显式return;构造函数依赖需提前绑定容器。

中间件没生效,八成是注册位置或闭包写法错了。
middleware() 方法里传字符串还是数组?
常见错误是把中间件名当函数调用:middleware('auth') 写成 middleware(auth()),后者会直接执行中间件类的 handle(),报错 Call to undefined function auth()。
正确写法只传字符串或数组:
- 单个中间件:
middleware('auth') - 多个中间件:
middleware(['auth', 'throttle:api']) - 带参数的中间件(如
throttle)必须用字符串形式,不能拆成函数调用
全局中间件 vs 路由组中间件注册位置搞混
新手常把中间件加在 app/Http/Kernel.php 的 $middlewareGroups['web'] 里,却在 API 路由中调用 —— 结果 session、csrf 都不生效,还查不出原因。
关键区别:
-
$middleware:全局,所有请求都走,慎加耗时逻辑 -
$middlewareGroups['web']:只对Route::middleware('web')生效,含 session、cookie 等 -
$middlewareGroups['api']:无状态,默认不带 session,别往里塞auth:web
比如想给某组 API 加 token 验证,得用 auth:sanctum,不是 auth:web。
中间件 handle() 里忘了 return $next($request)
这是最隐蔽的“静默失败”:中间件执行了,但后续逻辑完全不跑,浏览器卡住、无响应、日志也没报错。
典型错误写法:
public function handle($request, Closure $next)
{
if (! $request->user()) {
abort(401);
}
// ❌ 少了 return $next($request),请求在这里断掉
}
正确写法必须显式 return:
- 放行请求:
return $next($request) - 拦截请求:
return response(...)或return redirect(...) - 别用
abort()后不返回 —— 它抛异常,但中间件链不会自动兜底
中间件构造函数依赖注入失败
比如在中间件里注入 UserService,结果报 Target [App\Services\UserService] is not instantiable。
原因很直接:Laravel 在解析中间件实例时,只支持自动解析「绑定到容器的类」。如果 UserService 没在 AppServiceProvider 里用 $this->app->bind() 绑定,或者用了接口但没绑定实现,就会失败。
建议做法:
- 优先用容器已绑定的服务(如
Request,Response,Cache) - 自定义服务务必在
register()中绑定:$this->app->bind(UserService::class, function () { ... }) - 避免在构造函数里做重操作(如 DB 查询),
handle()才是执行时机
中间件的生命周期比控制器短,但它的执行顺序和依赖闭环更容易被忽略 —— 多半问题不在逻辑,而在注册点和返回值。











