
在 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() 不仅是语法要求,更是清晰表达逻辑依赖关系的良好实践。
