2016-09-23 68 views
0

我有一个带父 - 子行的数据库表,一个父 - 多子节点,由字段“parent”链接。在不使用递归的情况下迭代父节点PHP

我知道如何循环,并通过在PHP中使用递归功能打印jerarquy结构,但是当我试图用一个循环代码重现它,我不能在相同的格式呈现数据。这个代码示例列出数据库表中的所有项目,但不能下令,它首先打印顶层,我想经典:

Top 1 >> Level 1 >> Level 2 >> Level 3 
    Top 2 >> Level 1 
    Top 3 >> Level 1 >> Level 2 

    $parent = array(); 
    array_push($parent, 0); 
    while(!empty($parent)){ 
    foreach($parent as $key => $mother){ 
     unset($parent[$key]);  
     $sql = "SELECT * FROM levels WHERE parent = " . $mother; 
     $res = mysql_query($sql); 
     while($row=mysqli_fetch_object($res)){ 
     print $row->name . "<br />"; 
     array_push($parent, $row->id); 
     } // while 
    } // foreach 
    } // while 

这段代码的结果是

前1 顶2 前3 1级 ...

+0

在一个查询中选择需要的所有数据,然后对其进行操作不是更容易吗? – simon

+0

在递归函数的情况下,我认为使用多个SELECT会容易得多。在任何情况下,您都可以考虑使用与数据库中完全相同的结构填充数组。你如何遍历它以优先方式列出数据?递归很容易,我要求一个非递归的方法。 – Cesar

回答

1

这里最大的问题是为什么你想要它在一个非递归的方式?看到你有多个,而且看起来是一个未确定的子节点层次,这正是递归函数所擅长的。

如果只使用简单的循环,则需要具有尽可能多的嵌套循环,因为有子级;或者,跟踪当前节点ID,前一节点ID和父节点ID(复数形式),然后使用它来确定是否要创建新叶,退出叶或保持不变。
基本上:

Same parent == same leaf 
Different parent && parent == previous id, new leaf 
Different parent { when (parentList[idx--] == parent) == change leaf to idx leaf. 

这两种方法后者是目前为止最可扩展的,并且仅需要两个环:为所有的元素的一个主环路,和一个内环到滑回树,直到找到正确的父母ID。基本上,通过使用递归函数来模拟你所得到的一切。

我想评论的另一件事是你在循环中使用查询。这样做通常非常糟糕,因为它会以指数形式增加代码的时间消耗。在一个查询中获取所有节点要好得多,按父节点和ID排序。这样,您不必等待(n-1)* y ms(或更多)额外,其中n是记录数,y是运行查询一次所需的时间。
如果查询需要20ms运行,并且您有300条记录,那么您正在等待几乎6秒的额外等待时间!只是因为你在循环内部移动了查询,而不是正确排序(或使用JOIN)。
正如您所看到的,通过正确构建代码可以获得很多性能。不仅如此,它还会更容易阅读并维护您的代码。

摘要:使用递归函数,因为这是它们的作用,并将查询移到循环之外。

+0

这只是简单的兴趣。至于循环内部的SQL查询,你是完全正确的。我这样做是为了不让庞大数组中的PHP内存变得庞大,但是在其他情况下与我习惯的不同,你说得对,它会大大降低效率。 – Cesar

+0

很高兴我能帮到你。总是很高兴能够帮助别人学习,特别是当他们好奇并愿意这样做时。 :) 保持良好的工作! – ChristianF

相关问题