好吧,为了构建我的菜单我的菜单,我使用类似这样的数据库结构
2 Services 0 3 Photo Gallery 0 4 Home 0 5 Feedback 0 6 FAQs 0 7 News & Events 0 8 Testimonials 0 81 FACN 0 83 Organisation Structure 81 84 Constitution 81 85 Council 81 86 IFAWPCA 81 87 Services 81 88 Publications 81
要为现有子菜单指定另一个子菜单,我只需将其父ID作为父字段的值.父0表示顶级菜单
现在在另一个子菜单中创建子菜单时没有问题
现在这是我获取顶级菜单的子菜单的方式
<ul class="topmenu">
    <? $list = $obj -> childmenu($parentid); 
        //this list contains the array of submenu under $parendid
        foreach($list as $menu) {
            extract($menu);
            echo '<li><a href="#">'.$name.'</a></li>';
        }
    ?>
</ul>
我想做的是.
我想检查新菜单是否有其他子菜单
我想继续检查,直到它搜索每个可用的子菜单
我想在其特定列表项中显示其子菜单,如下所示
<ul>       
       <li><a href="#">Home</a>
        <ul class="submenu">
           ........ <!-- Its sub menu -->
           </ul>
       </li>
</ul>
J. *_*uni 20
这是针对此问题的" 一个查询,无递归 "解决方案的"开发人员友好"版本.
SQL:
SELECT id, parent_id, title, link, position FROM menu_item ORDER BY parent_id, position;
PHP:
$html = '';
$parent = 0;
$parent_stack = array();
// $items contains the results of the SQL query
$children = array();
foreach ( $items as $item )
    $children[$item['parent_id']][] = $item;
while ( ( $option = each( $children[$parent] ) ) || ( $parent > 0 ) )
{
    if ( !empty( $option ) )
    {
        // 1) The item contains children:
        // store current parent in the stack, and update current parent
        if ( !empty( $children[$option['value']['id']] ) )
        {
            $html .= '<li>' . $option['value']['title'] . '</li>';
            $html .= '<ul>'; 
            array_push( $parent_stack, $parent );
            $parent = $option['value']['id'];
        }
        // 2) The item does not contain children
        else
            $html .= '<li>' . $option['value']['title'] . '</li>';
    }
    // 3) Current parent has no more children:
    // jump back to the previous menu level
    else
    {
        $html .= '</ul>';
        $parent = array_pop( $parent_stack );
    }
}
// At this point, the HTML is already built
echo $html;
您只需要了解$ parent_stack变量的用法.
这是一个"LIFO"堆栈(Last In,First Out) - 维基百科文章中的图片价值千言万语:http://en.wikipedia.org/wiki/LIFO_%28computing%29
当菜单选项具有子选项时,我们将其父ID存储在堆栈中:
array_push( $parent_stack, $parent );
然后,我们立即更新$ parent,使其成为当前菜单选项ID:
$parent = $option['value']['id'];
在我们循环其所有子选项后,我们可以返回到上一级:
$parent = array_pop( $parent_stack );
这就是我们将父ID存储在堆栈中的原因!
我的建议是:考虑上面的代码片段并理解它.
欢迎提出问题!
我在这种方法中看到的一个优点是它消除了进入无限循环的风险,这可能在使用递归时发生.
J. *_*uni 16
使用像您这样的数据库结构,可以使用单个查询构建整个HTML菜单,而无需递归.
是的 - 我会重复:
这是我一直用自己的方法.
在这里粘贴代码 - 功能齐全:
跳转到第67行以查看有趣的部分("get_menu_html").
主循环从第85行开始.
有五个"可自定义"的HTML片段:
(如果我不担心制表,代码可能会更清晰.)
脚本末尾提供了用于创建和填充示例数据库的SQL.
您可以尝试让我们知道您的想法.
nic*_*ckf 11
您需要使用递归函数.从技术上讲,有几种方法可以做到,但递归确实是最好的选择.
以下是它如何工作的基本要点:
function drawMenu ($listOfItems) {
    echo "<ul>";
    foreach ($listOfItems as $item) {
        echo "<li>" . $item->name;
        if ($item->hasChildren()) {
            drawMenu($item->getChildren()); // here is the recursion
        }
        echo "</li>";
    }
    echo "</ul>";
}
这些属性和方法$item只是示例,我将根据您的需要实现这些,但我认为它会传达信息.
我建议您研究预排序的树遍历。有一篇关于这个问题的文章:
实际上,您将每个页面视为一个“节点”。每个节点都有一个对它的父节点的引用。当您更改节点的布局(添加子节点、移动节点等)时,您会重新计算每个节点的“左”和“右”值(上面的文章对此进行了非常详细的解释,并提供了 php 中源代码的链接)。您最终得到的是能够非常快速地确定给定节点是任何其他节点的直接或间接子节点,以及获取给定节点的所有子节点。
| 归档时间: | 
 | 
| 查看次数: | 31303 次 | 
| 最近记录: |