通过 PHP 使用 mysql 进行递归树遍历

Posted

技术标签:

【中文标题】通过 PHP 使用 mysql 进行递归树遍历【英文标题】:Recursive tree traversal with mysql through PHP 【发布时间】:2012-06-15 04:16:38 【问题描述】:

我正在为一位客户创建一份问卷,该问卷要求按 3 层级别组织问题。我已经成功创建了 U.I.但是,在过去的 3 个小时里,我一直在尝试从数据库中提取数据,以使所有内容都加载到正确的位置。数据库是由客户端组织的,所以我无法控制它:

id    description    parentId    
1      Level 1        0           
2      Level 2        0           
3      Level 1a       1   
4      Level 1b       1 
5      Level 1a1      3      

我在网站上发现了一个与我类似的问题,但是当我尝试它的解决方案时,我得到了以下无限重复:

代码:

function makeList($par_id = 0) 
    //your sql code here
    $result = mysql_query("SELECT * FROM pB_test WHERE parentId = $par_id");
    $pages = mysql_fetch_array( $result );

    if (count($pages)) 
        echo '<ul>';
        foreach ($pages as $page) 
            echo '<li>', $page['description'];
                makeList($page['parentId']);
                echo '</li>';
        
        echo '</ul>';
    


makeList();

输出:

1
3
5
5
l
l
3
5
5
l
l
3
5
5
l
l
3
5
5
l
l

有谁知道如何解决这个问题以及问题到底是什么?干杯

【问题讨论】:

MySQL 不支持递归JOINs,这是您真正需要的,但是如果您知道您只有三个级别并且永远只有三个级别,您可以将表连接到自己三倍 【参考方案1】:

每次都调用mysql服务器取结果不好

如果您有超过 100 行怎么办?或 200+

使用它只查询一次:

$result = mysql_query("SELECT * FROM test");
$arrs = array();

while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) 
    $arrs[] = $row;


function build_tree($arrs, $parent_id=0, $level=0) 
    foreach ($arrs as $arr) 
        if ($arr['parent_id'] == $parent_id) 
            echo str_repeat("-", $level)." ".$arr['name']."<br />";
            build_tree($arrs, $arr['id'], $level+1);
        
    


build_tree($arrs);

表格的常见示例

  id    name    parent_id

【讨论】:

您可以将global $arrs;(而不是将其作为参数传递)放在函数内部。它不再是黑匣子,但您将使用更少的内存。也使用 mysqli 代替 mysql。反正我喜欢。 这将始终获取完整的表,可能使用 TB 的 RAM - 不可能获取子树, @EugenRieck,只需将WHERE parent_id=$parent_id 子句添加到您的查询中,并将第二个参数添加到build_tree($arrs, $parent_id) 调用中。很明显它不适合大数据,但你会按照 OP 的要求将 TB 的结果包装在 &lt;ul&gt;&lt;li&gt; 中吗? 没错。我永远不会将 TB 包装到 &lt;ul&gt;&lt;li&gt;,但我会将 TB 放入数据库。这个损坏的代码将始终获取所有行,因此what if you have over 100 rows? or 200+ 的答案很简单:绝对不是这个,因为它会在任何大树上严重损坏。 谢谢@vladkras,到目前为止,这是我找到的最佳解决方案【参考方案2】:

递归执行:

function printChildQuestions($parentid) 
  $sql="SELECT * FROM pB_test WHERE parentID=$parentid";
  $result=mysql_query($sql);
  $i=0;
  while (true) 
    $row=mysql_fetch_array($result);
    if (!$row) break;
    if ($i==0) echo "<ul>";
    $i=1;
    echo '<li>'.$row['id'].'&nbsp;'.$row['description'].'&nbsp;'.$row['parentId'].'</li>';
    printChildQuestions($row['id']);
  
  if ($i>0) echo '</ul>';


printChildQuestions(0);

【讨论】:

有效!太感谢了!你今天赢得了互联网,伙计! 好的,然后我将如何将数据组织到 div 中,所以说 level1 是所有子级的容器,其中还有另一个 div 容器。那么 level2 是列表中的下一个容器吗? 你得问一个单独的问题:我是 php/SQL 人,不是 html 人,很抱歉 它应该仍然适用吧?如何拆分它以便每个级别都可以嵌套它自己的 html 标记?如果你做不到也没关系。不过感谢您的帮助! 基本上从我的代码开始:我回显&lt;ul&gt; 你应该回显你的起始HTML,&lt;/ul&gt; 成为你的结束HTML。 &lt;li&gt; ... &lt;/li&gt; 行是您的问题。所以我怀疑它应该像开始 &lt;div class=".."&gt;,结束 &lt;/div&gt; 和中间的格式化问题。

以上是关于通过 PHP 使用 mysql 进行递归树遍历的主要内容,如果未能解决你的问题,请参考以下文章

sql:如何存储树数据并进行递归遍历(通过查询)?

PHP二叉树递归遍历无限循环问题

使用MySQL 8的递归CTE遍历树

使用MySQL 8的递归CTE遍历树

PHP 递归遍历Cakephp线程数组(树行为)

数据结构-PHP 实现二分搜索树