concat() 是 Laravel 集合拼接的首选方法,它将另一集合所有值线性追加、不重索引、不覆盖、不 dedupe;需链式调用 values() 确保 JSON 输出为数组,并在合并后按需 groupBy + map + reduce 聚合归一化数据。

concat() 是 Laravel 集合拼接的首选方法,它把另一个集合的每一项“摊开”追加进来,不重索引、不覆盖、不 dedupe——就是纯粹拼接。别用 merge() 或 union() 替代,它们语义不同,容易踩坑。
什么时候该用 concat() 而不是 merge()
你手上有两个 Collection,想把所有元素堆成一个长列表,不管键名是否重复、类型是否一致,就该用 concat()。
-
merge()对数字键会重新索引(导致键错乱),对字符串键会覆盖(比如['id' => 1]和['id' => 2]合并后只剩后者) -
union()保留原始键,但只合并“不在当前集合里的键”,不是拼接逻辑 -
concat()不管键,只管值:它调用的是$other->all(),然后逐个push(),所以结果是预期的线性展开
concat() 后为什么还要链式调用 values()
因为 concat() 不重置键名,如果原集合含字符串键或非连续数字键,拼接后会出现稀疏/混合键结构,toArray() 输出 JSON 时可能变成对象而非数组。
- 例如:
collect(['a' => 1])->concat(collect([2, 3]))->toArray()得到['a' => 1, 0 => 2, 1 => 3],PHPjson_encode()会输出对象(因含字符串键) - 加
->values()强制转为连续数字索引:[1, 2, 3],确保 JSON 是标准数组 - 注意:
values()必须链在concat()后,且需重新赋值(它返回新集合,不修改原集合)
合并后要聚合?别绕弯,直接链 groupBy() + map()
单纯拼接只是第一步;真需求往往是“合并后按某字段归总”,比如同名用户 score 相加。这时不能停在 concat(),必须继续链式处理。
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
- 先
concat()把数据全拉平,再groupBy('name')分组,每组仍是 Collection,可继续操作 - 在
map()回调里用reduce()求和,记得传初始值(如0),否则空分组会抛UnexpectedValueException - 字段可能为字符串(如 API 返回
"score": "10"),得先map(fn($i) => ['score' => (int) $i['score']])统一类型,再reduce(),否则"10" + "20"变成"1020"
嵌套集合直接 push() 就出错?那是没展开
常见错误:循环中对每个关系调用 $collection->push($model->children),结果得到多层嵌套数组,而不是扁平列表。
-
$model->children是 Collection,push()把整个 Collection 当作一个元素塞进去 - 正确做法是换
concat():$collection = $collection->concat($model->children) - 如果来源混杂(比如有些是模型、有些是数组、有些是 null),先
filter()去空,再concat(),避免null导致后续map()报错
真正容易被忽略的是:合并后的数据若来自多个 API 或 JSON 解码,字段类型极不统一——score 可能是 int、string、null 甚至缺失。不做预处理就进 reduce() 或 sum(),结果不是 NaN 就是静默拼接。先用 map() 归一化,比在聚合回调里写一堆 ?? 0 更清晰可控。










