闭包中间件收不到 $app 参数是因为PHP匿名函数不自动继承父作用域,$app 非全局变量也非自动注入依赖,必须用 use() 显式捕获外部变量。

闭包中间件里为什么收不到 $app 参数
PHP 匿名函数不自动继承父作用域,$app 不是全局变量,也不是 Laravel 自动注入的依赖 —— 它根本不会凭空出现在闭包签名里。你写 function ($request, $next, $app),Laravel 路由/中间件调度器根本不会往第三个参数塞东西,直接报错或忽略。
闭包中间件传参唯一合法方式:use()
必须用 use 显式捕获外部变量,且变量必须在闭包定义前已存在。比如你在 routes/web.php 里写:
$allowedRoles = ['admin', 'editor'];
Route::middleware(function ($request, $next) use ($allowedRoles) {
if (!in_array(auth()->user()?->role, $allowedRoles)) {
abort(403);
}
return $next($request);
})->group(function () {
Route::get('/dashboard', function () { return view('dashboard'); });
});
-
$allowedRoles必须提前定义,不能在闭包里动态计算后才赋值 - 多个变量用逗号分隔:
use ($roles, $enabled, $timeout) - 如果要修改外部变量(比如计数器),得加引用:
use (&$counter) - 别
use ($request)或use ($next)—— 这俩已经作为参数传入,重复引入没意义还易混淆
想传运行时参数?别硬塞进闭包,改用路由模型绑定或中间件别名
闭包中间件天生不适合“每条路由传不同参数”。如果你需要类似 can:edit,post 这种动态行为:
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
- 注册命名中间件:
Route::middleware('can:edit,post'),参数会通过$request->route()拿到,再用parameter('post')提取绑定模型 - 或者把逻辑抽成类中间件,构造函数接收参数(但需配合服务容器绑定)
- 强行在闭包里做
request()->route()->parameter('xxx')是可行的,但破坏了闭包的简洁性,也容易漏判 null - 别试图在闭包里
app()获取实例再取配置 —— 这不是传参,是绕路查数据,且每次请求都执行,性能敏感场景要警惕
常见报错和对应检查点
遇到 Undefined variable 或中间件不生效,优先核对这几项:
- 变量是否真在
use()前就定义了?比如写在if块里却想在外面use→ 报错 - 变量名拼写是否一致?
use ($AllowedRoles)和$allowedRoles大小写不匹配 → 报错 - 闭包是否被缓存?改完路由后没跑
php artisan route:clear→ 旧逻辑还在跑 - 用了
Route::group()却把middleware写在闭包外(如Route::group([...])->middleware(...))→ 中间件不生效,Laravel 5.5+ 后只认链式调用或数组内配置
闭包传参看着轻量,但变量生命周期、作用域边界、缓存影响这三块最容易掉坑里,动手前先想清楚:这个参数是固定配置,还是每个请求都不同?前者用 use,后者绕开闭包更稳妥。










