Laravel中基于公共键为集合添加字段后无法提取数据问题
问题原因及解决方案
嘿,这个问题我之前也碰到过!核心是没搞清楚Laravel集合里each()和map()的设计差异:
each()方法本质是遍历执行副作用(比如打印日志、批量更新数据库),它会直接返回原集合的引用,不会帮你把回调里修改的元素整合到返回结果里。你在回调里修改的$record如果是数组(值传递),那改的只是回调内部的临时副本,原集合根本没变化;就算是对象类型,each()也不会处理返回值。- 而你需要的是修改每个元素并生成新集合,这时候
map()才是正确的选择——它会遍历每个元素,把回调返回的新元素收集起来,组成一个全新的集合返回。
修正后的代码
$usersDatas = $users->map(function ($record) use ($timeData) { $times = array_first($timeData, function ($value, $key) use ($record) { return $value['id'] === $record['id']; }); // 记得加个容错,避免找不到对应id时报错 if ($times) { $record['totalTime'] = $times['totalTime']; $record['spendTime'] = $times['spendTime']; $record['remainingTime'] = $times['remainingTime']; } // 关键!必须返回修改后的record,map会把这些返回值拼成新集合 return $record; }); dd($usersDatas);
额外的性能优化
如果你的$timeData数据量不小,每次用array_first()循环查找会拖慢速度。建议先把$timeData转成以id为键的结构,这样直接通过键取值就行,效率高很多:
// 先把timeData转成id为键的数组,后续直接通过$record['id']取值 $timeDataMap = collect($timeData)->keyBy('id')->toArray(); $usersDatas = $users->map(function ($record) use ($timeDataMap) { // 用null合并运算符处理找不到的情况 $times = $timeDataMap[$record['id']] ?? null; if ($times) { $record['totalTime'] = $times['totalTime']; $record['spendTime'] = $times['spendTime']; $record['remainingTime'] = $times['remainingTime']; } return $record; });
这样改完,不仅能得到正确的$usersDatas,运行效率也会提升不少~
内容的提问来源于stack exchange,提问作者davidvera
相关产品推荐
相关产品推荐

