如何基于关联数据格式化Laravel Collection?
解决Laravel Collection合并相同District的Zone问题
首先纠正下你提供的原始数据结构——PHP数组不允许重复键名,所以实际你的Collection应该是包含多个独立元素的集合,每个元素是带name和districts的数组,正确结构如下:
$originalCollection = collect([ [ 'name' => 'Test 1 Name', 'districts' => [ 'district' => '0001', 'zone' => 'blue' ] ], [ 'name' => 'Test 2 Name', 'districts' => [ 'district' => '0002', 'zone' => 'red' ] ], [ 'name' => 'Test 3 Name', 'districts' => [ 'district' => '0003', 'zone' => 'yellow' ] ], [ 'name' => 'Test 4 Name', 'districts' => [ 'district' => '0004', 'zone' => 'black' ] ], [ 'name' => 'Test 5 Name', 'districts' => [ 'district' => '0001', 'zone' => 'green' ] ] ]);
接下来用Laravel集合的链式方法实现合并逻辑:
$mergedCollection = $originalCollection // 按district字段分组 ->groupBy(fn($item) => $item['districts']['district']) // 处理每个分组内的元素 ->map(function($group, $district) { // 保留分组中第一个元素的name $targetName = $group->first()['name']; // 提取所有zone并去重 $zones = $group->pluck('districts.zone')->unique()->values(); // 构造最终的districts结构:单个zone用字符串,多个用数组 $districts = [ 'district' => $district, 'zone' => $zones->count() > 1 ? $zones->toArray() : $zones->first() ]; return ['name' => $targetName, 'districts' => $districts]; }) // 重置集合索引为连续数字 ->values();
执行后得到的$mergedCollection就是你想要的结构:
Collection {#1234 #items: array:4 [ 0 => array:2 [ "name" => "Test 1 Name" "districts" => array:2 [ "district" => "0001" "zone" => array:2 [ 0 => "blue" 1 => "green" ] ] ] 1 => array:2 [ "name" => "Test 2 Name" "districts" => array:2 [ "district" => "0002" "zone" => "red" ] ] 2 => array:2 [ "name" => "Test 3 Name" "districts" => array:2 [ "district" => "0003" "zone" => "yellow" ] ] 3 => array:2 [ "name" => "Test 4 Name" "districts" => array:2 [ "district" => "0004" "zone" => "black" ] ] ] }
核心逻辑说明:
groupBy:将所有拥有相同district的元素归为一组,方便后续合并pluck('districts.zone')->unique():提取分组内所有zone值并去重,避免重复数据- 最后根据zone数量决定返回数组还是单个字符串,完全匹配你要的输出格式
内容的提问来源于stack exchange,提问作者Lynx
相关产品推荐
相关产品推荐

