
本文介绍使用 Laravel 集合(Collection)的 groupBy 和 map 方法,将多对一关联查询结果(如分类与子分类)自动聚合成嵌套数组结构,避免手动循环判断,提升代码简洁性与执行效率。
本文介绍使用 Laravel 集合(Collection)的 groupBy 和 map 方法,将多对一关联查询结果(如分类与子分类)自动聚合成嵌套数组结构,避免手动循环判断,提升代码简洁性与执行效率。
在 Laravel 中执行表关联查询后,原始结果通常以扁平化集合形式返回(如每个子分类单独一行),但业务场景常需按父级字段(如 catname)归类聚合子项。例如,从 categories 与 subcategories 表联查获取 'Music' => 'Jazz' 等键值对后,期望输出为 'Music' => ['Jazz', 'Rock', 'Pop'] 这样的嵌套结构。
推荐采用 Laravel 内置的 Collection 链式操作实现零循环、高可读的转换:
$subcategories = Subcategory::select('subcategories.name as subcatname', 'categories.name as catname')
->join('categories', 'subcategories.idCategory', '=', 'categories.id')
->get();
$result = collect($subcategories)
->groupBy('catname')
->map(fn ($group) => $group->pluck('subcatname')->all())
->all();✅ 关键点说明:
- collect() 将 Eloquent 结果集转为 Collection,启用链式方法;
- groupBy('catname') 按类别名分组,生成以 catname 为键、对应子集为值的嵌套集合;
- map(...) 对每个分组执行映射:pluck('subcatname') 提取所有子分类名称,->all() 转为纯 PHP 数组;
- 最终 ->all() 将顶层 Collection 转为关联数组,符合预期格式。
⚠️ 注意事项:
- 若需保持键名一致性(如 'Movie' → 'Movies'),应在 select 中使用 DB::raw("categories.name AS catname") 或后续 mapKeys 处理;
- 数据量极大时(如万级记录),建议在数据库层用 GROUP_CONCAT(MySQL)或 STRING_AGG(PostgreSQL)预聚合,再交由应用层解析,避免内存压力;
- 此方案完全基于内存操作,不增加额外 SQL 查询,适合中等规模数据及快速开发场景。
该方法兼顾性能与可维护性,是 Laravel 生态中处理“一对多结果聚合”的标准实践。