如何为多维嵌套数组中的每个子元素动态添加 parent_id 字段

本文介绍在 php 中递归遍历多维嵌套数组(如树形结构),为每个非根节点自动注入 `parent_id` 字段,值为其直接父节点的 `uuid`,适用于权限菜单、组织架构等场景。

在处理具有层级关系的数据(如无限级分类、部门树、导航菜单)时,原始数据常以嵌套数组或对象形式存在,但缺少显式的父子关联字段(如 parent_id)。此时,需通过递归方式为每个子节点补全其父级唯一标识(如 uuid),从而便于后续数据库存储、前端渲染或扁平化处理。

以下是一个简洁、可复用的 PHP 解决方案,使用递归函数 + 引用传递优化(注意:原答案中未使用引用,对对象属性修改已生效,但若需兼容数组结构,建议增强健壮性):

function addParentId(&$nodes, $parentId = null) {
    if (!is_array($nodes) && !is_object($nod

es)) { 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 注入,是构建可持久化层级数据的基础工具。