You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP:遍历数组未按预期生成多层级结构数组问题

嘿,我懂你现在的困扰——你想把扁平的员工关联数组转换成带多层嵌套children的层级结构,但之前写的代码只能生成一级子节点,没法实现深层的嵌套关系。咱们来搞定这个问题!

核心思路

你的反转数组思路是对的(从底层员工往上处理),但关键问题是没有使用引用操作。如果只是直接修改原数组里的经理节点,当经理本身已经是某个上级的子节点时,你修改的只是原数组里的副本,而不是上级节点里的那个子对象。用引用的话,所有层级的修改都会联动更新,自然形成嵌套结构。

方法一:基于引用的迭代法(高效推荐)

这种方法只需要遍历数组两次,效率很高,适合处理大量数据:

// 假设你的原始数组是 $holding
$temp = [];
$result = [];

// 第一步:把所有员工存入临时数组,存储每个员工的引用,方便快速查找
foreach ($holding as &$employee) {
    $temp[$employee['number']] = &$employee;
    // 提前初始化children数组,避免后续操作报错
    $employee['children'] = [];
}
unset($employee); // 释放引用,防止后续代码意外修改

// 第二步:遍历临时数组,把每个员工挂载到直属经理的children列表中
foreach ($temp as $employee) {
    $managerNum = $employee['line_manager_number'];
    // 如果直属经理存在于数组中,就把当前员工加入经理的children
    if (isset($temp[$managerNum])) {
        $temp[$managerNum]['children'][] = &$temp[$employee['number']];
    } else {
        // 如果经理不在数组中(比如顶层Adam的经理57900不在列表里),就把当前员工作为顶层节点加入结果
        if ($employee['level'] === 0) {
            $result[] = &$temp[$employee['number']];
        }
    }
}

// 现在 $result 就是你要的多层级嵌套结构了
print_r($result);

为什么这个方法能生效?

通过引用存储每个员工,当我们把底层员工(比如Veronica)挂载到Larry的children里时,Larry本身已经是Edward的子节点,Edward又是Adam的子节点——所有层级的修改都是联动的,最终自然形成完整的树形结构。

方法二:递归法(简洁直观)

如果你的员工层级不多,递归法的代码更简洁易懂,逻辑也更直观:

/**
 * 递归构建层级结构
 * @param array $employees 所有员工数组
 * @param string|int $managerNumber 要查找下属的经理编号
 * @return array 下属的层级结构
 */
function buildEmployeeHierarchy($employees, $managerNumber) {
    $children = [];
    foreach ($employees as $employee) {
        // 如果当前员工的直属经理是传入的编号,就递归处理它的下属
        if ($employee['line_manager_number'] === $managerNumber) {
            $employee['children'] = buildEmployeeHierarchy($employees, $employee['number']);
            $children[] = $employee;
        }
    }
    return $children;
}

// 第一步:先找出所有顶层节点(level=0)
$topLevelEmployees = array_filter($holding, function($emp) {
    return $emp['level'] === 0;
});

// 第二步:为每个顶层节点构建完整的下属层级
$result = [];
foreach ($topLevelEmployees as $topEmp) {
    $topEmp['children'] = buildEmployeeHierarchy($holding, $topEmp['number']);
    $result[] = $topEmp;
}

print_r($result);

两种方法对比

  • 迭代法:效率更高,仅遍历数组两次,适合处理大量员工数据,不会有栈溢出风险。
  • 递归法:代码更简洁,逻辑容易理解,但如果层级过深(比如超过100层),可能会触发PHP的递归栈溢出错误。
你原来代码的问题

你之前的代码只把当前员工直接加到$holding[$v["line_manager_number"]]["children"]里,但这里修改的是原数组中经理节点的副本,而不是已经被挂载到上级节点里的那个经理对象。所以只有第一层下属会被添加,深层的嵌套关系无法建立——用引用就能解决这个核心问题。

内容的提问来源于stack exchange,提问作者pee2pee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:49:55