
本文讲解如何将数据库查询得到的扁平关联数组(含重复 id)高效重组为按 id 聚合、并内嵌 hobbies 数组的嵌套结构,提供简洁可靠的 php 实现方案及关键逻辑解析。
本文讲解如何将数据库查询得到的扁平关联数组(含重复 id)高效重组为按 id 聚合、并内嵌 hobbies 数组的嵌套结构,提供简洁可靠的 php 实现方案及关键逻辑解析。
在处理多对一关系(如用户与多个爱好)的数据库结果时,原始查询常返回扁平化数组——同一用户(相同 id)出现多次,每次携带一个爱好信息。但前端或后续业务通常需要结构化数据:每个用户仅出现一次,其所有爱好统一归入 hobbies 子数组中。这正是“按 ID 分组并嵌套”的典型场景。
核心思路是:以 id 为键构建临时关联数组(哈希表),避免重复初始化,动态追加 hobby 项。以下是推荐实现:
$new_persons = [];
foreach ($persons as $item) {
$id = $item['id'];
// 若该 id 尚未初始化,则创建基础用户结构(只设 id 和 name)
if (!isset($new_persons[$id])) {
$new_persons[$id] = [
'id' => $id,
'name' => $item['name'],
'hobbies' => []
];
}
// 无论是否首次出现,均向该 id 对应的 hobbies 数组追加新爱好
$new_persons[$id]['hobbies'][] = [
'hobbyId' => $item['hobbyId'],
'hobbyName' => $item['hobbyName']
];
}
// 最终转换为索引数组(去除 id 键,保持顺序)
$new_persons = array_values($new_persons);
✅ 为什么原代码失败?
- 使用 in_array($item['id'], $newArray) 判断存在性 —— 错误地将 $newArray 当作值列表,而它实际是关联数组(键为 id 或索引),导致始终不匹配;
- 缺乏对 hobbies 数组的初始化检查($newArray['hobbies'] 在首次访问时未定义,引发 Notice);
- 混淆了 $newArray(用于存储结果)和 $detail(临时结构),逻辑分支混乱。
⚠️ 注意事项:
- 确保输入 $persons 是合法的 PHP 关联数组(非对象或 JSON 字符串);
- 若原始数据中 name 可能因行不同而变化(如部分记录 name 为空),建议在首次初始化时严格取值,后续忽略更新,或添加校验逻辑;
- 如需保持原始顺序且 ID 不连续,array_values() 是必要步骤;若需按 ID 升序输出,可改用 ksort($new_persons) 后再 array_values()。
该方案时间复杂度为 O(n),空间复杂度为 O(m+k)(m 为唯一用户数,k 为总爱好数),简洁、健壮、易于扩展(例如支持多级嵌套或添加其他聚合字段)。











