使用php和mysql查询结果获取父节点下的所有子节点、孙子节点等

使用php和mysql查询结果获取父节点下的所有子节点、孙子节点等,php,mysql,database,tree,nodes,Php,Mysql,Database,Tree,Nodes,我一直在想办法,但我什么也没得到。希望有人能来救我 我的问题是,我使用邻接列表数据模型在mysql中生成层次结构数据。我可以将表(见下文)检索到一个多维数组中,每个项目都有关联数组。我想做的是,一旦我得到这个数组,我想得到另一个数组,其中包含父id(包括父项)下的所有节点(子节点、孙子节点等) 在MySQL中,我的表如下所示: id name parent_id 1 Electronics 0 2 Televisions 1 3 Po

我一直在想办法,但我什么也没得到。希望有人能来救我

我的问题是,我使用邻接列表数据模型在mysql中生成层次结构数据。我可以将表(见下文)检索到一个多维数组中,每个项目都有关联数组。我想做的是,一旦我得到这个数组,我想得到另一个数组,其中包含父id(包括父项)下的所有节点(子节点、孙子节点等)

在MySQL中,我的表如下所示:

id     name       parent_id
1  Electronics          0
2  Televisions          1
3  Portable Electronics 1
4  Tube                 2
5  LCD                  2
6  Plasma               2
7  Mp3 Players          3
8  CD Players           3
9  2 Way Radios         3
10 Flash                7
function fetch_recursive($tree, $parent_id, $parentfound = false, $list = array())
{
    foreach($tree as $k => $v)
    {
        if($parentfound || $k == $parent_id)
        {
            $rowdata = array();
            foreach($v as $field => $value)
                if($field != 'children')
                    $rowdata[$field] = $value;
            $list[] = $rowdata;
            if($v['children'])
                $list = array_merge($list, fetch_recursive($v['children'], $parent_id, true));
        }
        elseif($v['children'])
            $list = array_merge($list, fetch_recursive($v['children'], $parent_id));
    }
    return $list;
}
我可以使用此代码将所有行检索到具有此代码的关联数组中

$r = mysql_query("SELECT * FROM test ");
        $data = array();
        while($row = mysql_fetch_assoc($r)) {
         $data[] = $row;
         }      
获取结果:

Array 
( 
    [0] => Array 
    ( 
        [id] => 1 
        [name] => Electronics 
        [parent_id] => 0 
    ) 
    [1] => Array 
    ( 
        [id] => 2 
        [name] => Televisions 
        [parent_id] => 1 
    ) 
    [2] => Array 
    ( 
        [id] => 3 
        [name] => Portable Electronics 
        [parent_id] => 1 
    )
    [3] => Array 
    (
        [id] => 4 
        [name] => Tube 
        [parent_id] => 2 
    )
    [4] => Array 
    (
        [id] => 5 
        [name] => LCD 
        [parent_id] => 2
    )
    [5] => Array
    (
        [id] => 6 
        [name] => Plasma 
        [parent_id] => 2
    )
    [6] => Array
    (
        [id] => 7 
        [name] => Mp3 Players 
        [parent_id] => 3 
    )
    [7] => Array 
    (
        [id] => 8 
        [name] => CD Players 
        [parent_id] => 3
    )
    [8] => Array 
    (
        [id] => 9 
        [name] => 2 Way Radios 
        [parent_id] => 3
    )
    [9] => Array
    (
        [id] => 10 
        [name] => Flash 
        [parent_id] => 7 
    ) 
)
有了这些结果,我想用一个id来过滤它

例如,我想要一个id为3的便携式电子设备下每个节点的关联数组

它将返回一个包含ID为的行的数组:

  • 3个便携式电子设备(必须包括选定的母公司)
  • 7个Mp3播放器(儿童)
  • 8个CD播放器(儿童)
  • 9台双向收音机(儿童)
  • 10闪光(孙儿)
如果Flash有孩子,它也会把孩子还给他们

因此,最终结果将返回一个与上面类似的数组,但是只返回这些项

请注意: 我不是在寻找一个创建树结构多维数组的函数(已经有了解决方案)。我想构建一个函数:fetch_recursive($id),它接收一个id并返回该级别和下面级别中的所有项等。

希望这有帮助


提前感谢

这里有一种方法可以让您更进一步,您可以决定如何构建结果数组以及选择包含哪些字段。这没有经过测试,但您应该看到逻辑

// connect to db

// set id counter
$ids = 0;

// declare array
$categories = new Array();

// determine max ids
$query = mysql_query("SELECT COUNT(1) AS ids FROM test");
$result = mysql_fetch_array(query); // get result
$count = $result['ids'];

// loop through ids for parents
for($ids = 0; $ids <= $count; $ids++) {
  $query1 = mysql_query("SELECT * FROM test WHERE id = '" . $ids . "'");
  $query2 = mysql_query("SELECT id, name, parent_id FROM test WHERE parent_id = '" . $ids . "'");
  // check if has children
  if(mysql_num_rows($query2) > 0) {
    // iterate through children and add to array
    while (mysql_fetch_array($query2) as $row) {
      $categories[$ids]['child'][$row['id']] = $row['name'];
    }
  }
  // check if has siblings
  if(mysql_num_rows($query1) > 0) {
    // iterate through children and add to array
    while (mysql_fetch_array($query2) as $row) {
      $categories[$ids]['sibling'][$row['id']] = $row['name'];
    }
  }
}
//连接到数据库
//设置id计数器
$ids=0;
//声明数组
$categories=新数组();
//确定最大ID
$query=mysql_query(“从测试中选择COUNT(1)作为ID”);
$result=mysql_fetch_数组(查询);//得到结果
$count=$result['id'];
//循环检查家长的ID
对于($ids=0;$ids 0){
//遍历子项并添加到数组
while(mysql\u fetch\u数组($query2)作为$row){
$categories[$id]['child'][$row['id']]=$row['name'];
}
}
//检查是否有兄弟姐妹
如果(mysql_num_rows($query1)>0){
//遍历子项并添加到数组
while(mysql\u fetch\u数组($query2)作为$row){
$categories[$id]['sibling'][$row['id']]=$row['name'];
}
}
}
编辑: 我之前发布了一个解决方案,用你给出的输出构建一个多维数组,以及一种从该特定数组中获取特定
id
的所有子元素的方法。我现在已经知道了如何直接从输出中检索子元素(无需首先执行
buildtree()
函数:

function fetch_recursive($src_arr, $currentid, $parentfound = false, $cats = array())
{
    foreach($src_arr as $row)
    {
        if((!$parentfound && $row['id'] == $currentid) || $row['parent_id'] == $currentid)
        {
            $rowdata = array();
            foreach($row as $k => $v)
                $rowdata[$k] = $v;
            $cats[] = $rowdata;
            if($row['parent_id'] == $currentid)
                $cats = array_merge($cats, fetch_recursive($src_arr, $row['id'], true));
        }
    }
    return $cats;
}
echo '<pre>';
print_r(fetch_recursive(buildtree($a), 3));
echo '</pre>';
要使用上述函数,只需将输出数组
$data
传递给第一个参数,并在第二个参数中传递要从中检索子元素的
id

例:

这将为
id
3
提供正确的数组结构(如本答案最后一个代码框中的示例所示)


原始答案:

到目前为止,我还没有开始编写递归函数来用这种设计构建嵌套树。我相信还有很多其他人编写过类似的函数,但这一个肯定适合您:

function buildtree($src_arr, $parent_id = 0, $tree = array())
{
    foreach($src_arr as $idx => $row)
    {
        if($row['parent_id'] == $parent_id)
        {
            foreach($row as $k => $v)
                $tree[$row['id']][$k] = $v;
            unset($src_arr[$idx]);
            $tree[$row['id']]['children'] = buildtree($src_arr, $row['id']);
        }
    }
    ksort($tree);
    return $tree;
}
此函数将递归地从邻接列表中构建一棵树,并按升序排列id。这也使每个父/子的
id
成为每个信息数组的键

此代码:

$r = mysql_query("SELECT * FROM test ");
$data = array();
while($row = mysql_fetch_assoc($r)) {
    $data[] = $row;
}
echo '<pre>';
print_r(buildtree($data));
echo '</pre>';
要将特定
id
的所有子节点放到一维数组中,可以使用以下函数:

function fetch_recursive($src_arr, $currentid, $parentfound = false, $cats = array())
{
    foreach($src_arr as $row)
    {
        if((!$parentfound && $row['id'] == $currentid) || $row['parent_id'] == $currentid)
        {
            $rowdata = array();
            foreach($row as $k => $v)
                $rowdata[$k] = $v;
            $cats[] = $rowdata;
            if($row['parent_id'] == $currentid)
                $cats = array_merge($cats, fetch_recursive($src_arr, $row['id'], true));
        }
    }
    return $cats;
}
echo '<pre>';
print_r(fetch_recursive(buildtree($a), 3));
echo '</pre>';
基于上面的
buildtree()
函数,假设我们想要获得
id
3的所有子节点:

Array
(
    [0] => Array
        (
            [id] => 3
            [name] => Portable Electronics
            [parent_id] => 1
        )

    [1] => Array
        (
            [id] => 7
            [name] => Mp3 Players
            [parent_id] => 3
        )

    [2] => Array
        (
            [id] => 10
            [name] => Flash
            [parent_id] => 7
        )

    [3] => Array
        (
            [id] => 8
            [name] => CD Players
            [parent_id] => 3
        )

    [4] => Array
        (
            [id] => 9
            [name] => 2 Way Radios
            [parent_id] => 3
        )

)

那么,您试图构建的函数是:
fetch\u recursive($id)
它接收一个
ID
并返回该级别和以下级别中的所有项。听起来像一个简单的递归函数。你尝试过做什么?我们能看到你的代码吗?是的,这就是我想要的,我尝试过编写一些代码,但没有成功:|我知道你现在想要什么。看看我修改过的解决方案。然后非常感谢你,这正是我想要的。几天前,你在这里发布的其他一些代码对我非常有用,无论如何,我相信它对其他人来说会很有用。再次感谢你的详细回复。谢谢。这很好。但我想看看在BFS中是否可以获取递归子级。如果可以,请发布t你好,赞恩,你能解释一下如何打印这棵树吗?