
本文介绍在 php 中递归遍历多维嵌套数组(如树形结构),为每个非根节点自动注入 `parent_id` 字段,值为其直接父节点的 `uuid`,适用于权限菜单、组织架构等场景。
在处理具有层级关系的数据(如无限级分类、部门树、导航菜单)时,原始数据常以嵌套数组或对象形式存在,但缺少显式的父子关联字段(如 parent_id)。此时,需通过递归方式为每个子节点补全其父级唯一标识(如 uuid),从而便于后续数据库存储、前端渲染或扁平化处理。
以下是一个简洁、可复用的 PHP 解决方案,使用递归函数 + 引用传递优化(注意:原答案中未使用引用,对对象属性修改已生效,但若需兼容数组结构,建议增强健壮性):
function addParentId(&$nodes, $parentId = null) {
if (!is_array($nodes) && !is_object($nodes)) {
return;
}
// 若为对象,转换为数组便于统一处理(可选)
$items = is_object($nodes) ? (array)$nodes : $nodes;
foreach ($items as &$item) {
// 仅当存在 parentId 且当前节点非根节点时设置 parent_id
if ($parentId !== null) {
$item->parent_id = $parentId; // 对象写法(推荐保持对象结构)
// 或 $item['parent_id'] = $parentId; // 若为关联数组
}
// 递归处理子节点(childrens 字段需存在且为非空数组/对象)
if (isset($item->childrens) && (!empty($item->childrens))) {
addParentId($item->childrens, $item->uuid);
}
}
}
// 使用示例(基于原始 JSON 数据)
$json = '{"array": [{"uuid":7,"nome":"Parent","ativo":1,"childrens":[{"uuid":9,"nome":"Child","ativo":1,"childrens":[{"uuid":70,"nome":"Child of Child","ativo":1,"childrens":[{"uuid":391,"nome":"Child of Child of Child","ativo":1,"childrens":[]}]}]}]}]}]}';
$object = json_decode($json);
foreach ($object->array as $root) {
addParentId($root->childrens, $root->uuid);
}
echo json_encode($object, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);✅ 关键要点说明:
- 递归入口清晰:根节点无 parent_id,其 childrens 的 parent_id 设为根节点 uuid;子节点同理逐层向下传递;
- 对象优先操作:json_decode() 默认返回 stdClass 对象,直接使用 -> 赋值更高效,避免数组与对象混用导致的 Notice;
- 安全判断:检查 childrens 是否存在且非空,防止 null 或缺失键引发错误;
- 可扩展设计:函数支持传入任意层级子集(不局限于 $object->array),便于单元测试或局部更新。
⚠️ 注意事项:
- 若原始数据是关联数组(json_decode($json, true)),请将 $item->parent_id 改为 $item['parent_id'],并确保 childrens 键名一致;
- 深度过大的嵌套可能导致 PHP 递归栈溢出(默认 xdebug.max_nesting_level=256),生产环境建议增加深度限制或改用迭代(栈模拟)实现;
- 如需保留原始键顺序或处理特殊字段(如 id/pid 别名),可在函数内增加映射配置参数。
该方法逻辑清晰、侵入性低,一次调用即可完成整棵树的 parent_id 注入,是构建可持久化层级数据的基础工具。










