2014-01-19 99 views
2

我有一个对象列表,它是父对象与“n”孩子的其他对象。递归列表函数

为了列出的父母,我已经成功与该这样做:

echo "<ol>"; 
      foreach ($indicator_dimensions as $dimension) { 
       if (empty($dimension->parent)) { 
        echo "<li>"; 
        echo $dimension->dimension; 
        $subdimensions = Indicator_dimension::find_by_sql("SELECT * FROM indicator_dimension where parent=".$dimension->id); 
        if (count($subdimensions) != 0) { 
         find_leaves($subdimensions); 
        } 
        echo "</li>"; 
       } 
      } 
      echo "</ol>"; 

要列出自己的孩子,我使用这个功能:

function find_leaves($dimensions){ 
       echo "<ol>"; 
       foreach ($dimensions as $dimension) { 
        echo "<li>"; 
        echo $dimension->dimension; 
         if (!empty($dimension->parent)) { 
          $subdimensions = Indicator_dimension::find_by_sql("SELECT * FROM indicator_dimension where parent=".$dimension->id); 
          if (count($subdimensions) != 0) { 
           find_leaves($subdimensions); 
          } 
         } 
        echo "</li>"; 
       } 
       echo "</ol>"; 
      } 

虽然它的工作,这是丑陋的代码,我想重构,但没有得到大脑...

提前欣赏提高任何提示!

+2

首先,您应该阅读更多有效的技术来存储和检索关系数据库中的树数据,例如[嵌套集](http://en.wikipedia.org/wiki/Nested_set_model)或[封闭表](http:// karwin.blogspot.de/2010/03/rendering-trees-with-closure-tables.html)。 – bitWorking

回答

0

这看起来像你需要一个经典的树实现。它由具有n个子节点的节点组成。 我写了一个小例子实现here。我知道遍历不是很干净,但它满足您的需求。

我将所有的魔力委托给ListRenderer的遍历方法。这挖recursivley到目前所经过的节点的孩子:

protected function traverse(Node $node) { 
    if($node->__toString()) $this->output .= '<li>'.$node.'</li>'; //echo current node 
    if($node->hasChildren()) { 
     $this->output .= '<ol>'; 
     foreach($node->getChildren() as $child) { 
      $this->traverse($child);        //repeat for children 
     } 
     $this->output .= '</ol>'; 
    } 
} 

请注意,根节点没有回音<li>root</li>,因为它的标签是空的。所以这个例子的输出结果是:

<ol> 
    <li>sub1</li> 
    <li>sub2</li> 
    <ol> 
     <li>sub a</li> 
     <li>sub b</li> 
     <li>sub c</li> 
    </ol> 
    <li>sub3</li> 
</ol> 

这正是你想要的。


如果您想了解更多关于树的遍历,看看the wikipedia article about tree traversal