Laravel如何向each闭包注入外部变量/依赖,尝试使用global无效
Laravel 集合each闭包导入外部变量的正确实现
根因说明
Laravel集合的each方法没有特殊的作用域改写逻辑,完全遵循原生PHP的闭包运行规则:
- 闭包拥有独立的词法作用域,默认无法直接访问外层方法/函数中定义的局部变量
- 此前尝试用
global关键字引入变量失败的核心原因:global的作用是从全局超全局作用域(即$GLOBALS数组)中引入同名变量,而代码里的$user_project是show控制器方法内部的局部变量,根本没有被挂载到全局作用域,因此通过global永远无法拿到外层定义的实际值。
正确实现方式
PHP提供了use关键字专门用于将闭包外层作用域的变量导入到闭包内部可访问的范围,使用方法是在闭包的参数列表后追加use (需要导入的变量列表)。
仅需要修改each方法中的闭包定义,把$user_project通过use关键字导入即可,完整修正后的代码如下:
public function show(Project $project) { $client = $project->client; $users = $project->projectUsers(); $user_project = UserProject::where('user_id', $users[0]->id) ->where('project_id', $project->id) ->first()->id; $users->each(function ($user) use ($user_project) { $user->total_hours = $user->usersHoursPerProject($user_project); }); return Inertia::render('Projects/show', [ 'client' => $client, 'users' => $users, 'project' => $project ]); }
注意事项
- 如果需要在闭包内部修改外层变量本身的值,需要在
use导入时加上引用符号&,比如use (&$counter),否则闭包拿到的只是变量的值副本;当前场景仅需要读取$user_project的固定值,不需要加引用。 - 当前代码存在可优化的逻辑隐患:查询
$user_project时仅取了集合中第一个用户$users[0]对应的关联记录ID,但遍历所有项目用户时,给每个用户的usersHoursPerProject方法都传入了同一个第一个用户的关联ID,大概率不符合业务预期,建议遍历每个用户时动态获取当前用户对应的关联记录ID,而不是复用第一个用户的固定值。 - 如果
$users集合为空,直接读取$users[0]->id会触发空值访问错误,可以补充空判断做兜底。
内容的提问来源于stack exchange,提问作者Alberto Martínez
相关产品推荐
相关产品推荐

