Laravel中如何合并两个对象集合并保留所有字段不被覆盖
Laravel集合默认的merge()方法是按索引位置替换元素,不会按业务关联字段(如本次的id)合并单条数据的属性,所以才会出现第二个集合完全覆盖第一个集合内容的情况。
通用解决方案(兼容元素顺序不一致、存在缺项的场景)
步骤1:生成第二个集合的id映射表
将第二个集合以id为键转为关联集合,避免嵌套遍历提升匹配效率:
$itemMap = $collection2->keyBy('id');
步骤2:遍历合并属性
$merged = $collection1->map(function ($item) use ($itemMap) { $targetItem = $itemMap->get($item['id']); // 没有匹配到对应id数据直接返回原有内容 if (!$targetItem) { return $item; } // 合并两个元素的属性,同名字段优先保留第一个集合的值,需要优先保留第二个集合的值则调换两个toArray()的顺序 return array_merge($item->toArray(), $targetItem->toArray()); });
如果集合元素是Eloquent模型对象,不需要转成数组可以直接追加属性:
$merged = $collection1->map(function ($item) use ($itemMap) { $targetItem = $itemMap->get($item->id); if (!$targetItem) { return $item; } // 仅追加第一个集合不存在的字段 foreach ($targetItem->getAttributes() as $key => $value) { if (!$item->hasAttribute($key)) { $item->setAttribute($key, $value); } } return $item; });
如果确认两个集合的元素顺序完全一致、id一一对应没有缺漏,可以用更简洁的zip方法实现:
$merged = $collection1->zip($collection2)->map(function ($pair) { return array_merge($pair[0]->toArray(), $pair[1]->toArray()); });
内容的提问来源于stack exchange,提问作者Anibal Cardozo
相关产品推荐
相关产品推荐

