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

PHP递归提取父子数据结构完整分支问题排查

问题:从层级对象数组中提取节点及其所有父节点

场景与示例数据

从SQL查询得到一个对象数组,每个对象包含id、type、title、parent_id字段,示例数据如下:

$array = array(
    0 => (object) array( 'id' => 1, 'type' => 'label', 'title' => 'Product Categories', 'parent_id' => 0, ), 
    1 => (object) array( 'id' => 2, 'type' => 'label', 'title' => 'Shoes', 'parent_id' => 1, ), 
    2 => (object) array( 'id' => 3, 'type' => 'label', 'title' => 'T-Shirts', 'parent_id' => 1, ), 
    3 => (object) array( 'id' => 4, 'type' => 'label', 'title' => 'With Print', 'parent_id' => 2, ), 
    4 => (object) array( 'id' => 5, 'type' => 'label', 'title' => 'Without Print', 'parent_id' => 2, ), 
    5 => (object) array( 'id' => 6, 'type' => 'label', 'title' => 'Brands', 'parent_id' => 2, ), 
    6 => (object) array( 'id' => 7, 'type' => 'label', 'title' => 'Blue', 'parent_id' => 3, ), 
    7 => (object) array( 'id' => 8, 'type' => 'label', 'title' => 'Red', 'parent_id' => 3, )
);

期望输出

根据指定ID(如7),提取该节点及其所有父节点组成数组,示例预期结果:

Array
(
    [0] => stdClass Object
        (
            [id] => 7
            [type] => "label"
            [title] => "Blue"
            [parent_id] => 3
        )
    [1] => stdClass Object
        (
            [id] => 3
            [type] => "label"
            [title] => "T-Shirts"
            [parent_id] => 1
        )
    [2] => stdClass Object
        (
            [id] => 1
            [type] => "label"
            [title] => "Product Categories"
            [parent_id] => 0
        )
)

当前问题

调用原递归函数后,仅返回起始ID对应的条目,以ID7为例,实际输出:

array ( 0 => (object) array( 'id' => 7, 'type' => 'label', 'title' => 'Blue', 'parent_id' => 3, ), ) 

原函数逻辑问题

原递归函数存在两处关键错误:

  1. 循环中每次匹配失败就将$next_id设为false,若目标节点不在数组起始位置,后续循环会覆盖正确的匹配状态,导致无法触发递归
  2. 当parent_id为0时,$next_id != false的判断会把0视为布尔值false,直接终止递归,无法获取根节点

修正方案

方案1:修复递归逻辑

调整循环逻辑,先找到目标节点再处理父ID,同时修正终止条件:

function getParentSelect($list, $targetId) {
    $result = [];
    // 遍历数组找到当前目标节点
    foreach ($list as $item) {
        if ($item->id == $targetId) {
            $result[] = $item;
            // 父ID不为0时,递归查找父节点
            if ($item->parent_id !== 0) {
                $parentNodes = getParentSelect($list, $item->parent_id);
                $result = array_merge($result, $parentNodes);
            }
            break;
        }
    }
    return $result;
}

// 调用示例
$branch = getParentSelect($array, 7);

方案2:预处理映射优化效率

如果数组数据量较大,推荐先将数组转为以id为键的映射表,避免每次递归遍历整个数组,提升查找效率:

// 预处理数组,构建ID到对象的映射
function buildIdMap($list) {
    $idMap = [];
    foreach ($list as $item) {
        $idMap[$item->id] = $item;
    }
    return $idMap;
}

// 提取节点及其父节点
function getParentSelect($idMap, $targetId) {
    $result = [];
    $currentId = $targetId;
    // 循环查找直到节点不存在或父ID为0
    while (isset($idMap[$currentId])) {
        $result[] = $idMap[$currentId];
        $currentId = $idMap[$currentId]->parent_id;
        // 父ID为0时终止循环(若根节点ID为0可根据需求调整)
        if ($currentId === 0) {
            break;
        }
    }
    return $result;
}

// 调用示例
$idMap = buildIdMap($array);
$branch = getParentSelect($idMap, 7);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 13:10:25