我有一个对象列表,这些对象是具有“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>";
}
虽然它正在运行,但是我想重构它的丑陋代码但却没有动脑......
事先欣赏任何增强技巧!
答案 0 :(得分: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。