
在 laravel 8 的 query builder 闭包(如 `where()` 的回调函数)中,外部作用域变量默认不可访问;必须通过 `use()` 显式引入,否则会触发“undefined variable”错误。
在使用 laravel 的数据库查询构造器(Query Builder)时,若需在闭包回调(例如 where(function ($query) { … }))中引用定义在闭包外部的变量(如 $p1Array),必须显式使用 use() 语法将变量传入闭包作用域。这是 php 语言本身的特性:匿名函数默认无法访问父作用域中的变量,除非显式声明。
以下是你原始代码的问题所在:
->where(function($query) { if (Arr::has($p1Array, 'includeProcessJob')) { // ❌ $p1Array 未定义! $query->where('ndt_job_status_id', '=', 1) ->orWhere('ndt_job_status_id', '=', 2); } })
虽然 $p1Array 在闭包外已定义,但未通过 use() 引入,因此在闭包内部无法识别,导致运行时报错 Undefined variable: p1Array。
✅ 正确写法如下:
$job_bookings = DB::table('job_bookings') ->where('client_id', '=', $p1Array['incharge_id']) ->where(function ($query) use ($p1Array) { // ✅ 关键:use($p1Array) if (Arr::has($p1Array, 'includeProcessJob')) { $query->where('ndt_job_status_id', '=', 1) ->orWhere('ndt_job_status_id', '=', 2); } else { $query->where('ndt_job_status_id', '=', 1); } });
⚠️ 注意事项:
- use() 中可传递多个变量,用逗号分隔:use ($p1Array, $statusId, $flag);
- 若需在闭包内修改外部变量(而非仅读取),需加 & 引用符号:use (&$p1Array);
- 避免在 use() 中传入大型对象或集合,可能影响内存与可读性;必要时可提前提取所需值(如 $includeProcessJob = Arr::has($p1Array, ‘includeProcessJob’),再 use ($includeProcessJob));
- Laravel 9+ 同样适用该规则,此机制与 PHP 版本无关,由匿名函数作用域规则决定。
总结:闭包不是“自动继承”外部变量的作用域,而是需要开发者主动声明依赖——use() 不仅是语法要求,更是清晰表达逻辑依赖关系的良好实践。