分层树菜单 - PHP / MySQL

时间:2014-05-01 21:11:35

标签: php mysql

在处理动态菜单w / CRUD时,我遇到了一些问题。它可以工作,但是有一些额外的标签被插入不应该的地方,并且在我与世界分享之前无法弄清楚如何清理它。我以此作为起点,然后将其改为使用手风琴菜单(http://www.phpro.org/tutorials/Simple-Mysql-PHP-Menu.html)。

下面是表中的数据(我更改了前两个字段的名称,使其适合从menu_item_id到id,从menu_parent_id到pid的SO格式)。

id  pid    menu_item_name         menu_url  sortorder status 
1      0    Settings                            0   ACTIVE
2      5    Grid Demo            grid.php           ACTIVE
3      5    setGridOptions       gridoptions.php    ACTIVE
4      1    Menu Items           adminmenu.php  1   ACTIVE
5      0    Grid Settings                       100 ACTIVE
6      1    General Settings     settings.php   100 ACTIVE

这是连接到mysql数据库并创建分层树数组以使其工作的PHP:

include 'db.php';
$sql = "SELECT * FROM menu_items WHERE status = \"ACTIVE\" ORDER BY sortorder, menu_item_name";
$query = $db->query($sql);


while($data = $query->fetch(PDO::FETCH_ASSOC))
   // loop over the results
    {
        // Assign by reference
        $thisref = &$refs[ $data['menu_item_id'] ];

        // add the the menu parent
        $thisref['menu_item_id'] = $data['menu_item_id'];
        $thisref['menu_parent_id'] = $data['menu_parent_id'];
        $thisref['menu_item_name'] = $data['menu_item_name'];
        $thisref['menu_url'] = $data['menu_url'];

        // if there is no parent id
        if ($data['menu_parent_id'] == 0)
        {
            $list[ $data['menu_item_id'] ] = &$thisref;
        }
        else
        {
            $refs[ $data['menu_parent_id'] ]['children'][ $data['menu_item_id'] ] = &$thisref;
        }
    }

    function create_list( $arr )
    {
        $html = "";
        foreach ($arr as $key=>$v) 
        {
            if ($v['menu_parent_id'] == '0')
            {
             $html .= '<a class="menuitem submenuheader" href="'. $v['menu_url'] .'">'.$v['menu_item_name']."</a>\n";
             $html .= "<div class=\"submenu\">\n<ul>\n";
             $html .= "<li>" . create_list($v['children']) . "</li>";
             $html .= "</ul>\n";
            }
            else{
             $html .= '<li><a id="' . $v['menu_item_id'] . '">'.$v['menu_item_name']."</a></li>\n";
                }
            }
        $html .= "</div>\n";
        return $html;
    }
echo "<div class=\"glossymenu\">";
    echo create_list( $list );
echo "</div>";

当我运行它时,它输出以下内容:

<div class="glossymenu"><a class="menuitem submenuheader">Settings</a>
<div class="submenu">
<ul>
<li><li><a id="4">Menu Items</a></li>
<li><a id="6">General Settings</a></li>
</div>
</li></ul>
<a class="menuitem submenuheader" href="">Grid Settings</a>
<div class="submenu">
<ul>
<li><li><a id="2">Grid Demo</a></li>
<li><a id="3">setGridOptions</a></li>
</div>
</li></ul>
</div>
</div>  

正如您所看到的有额外<li>个标签,</ul>出错了 现场(应该在</div>之后)除此之外,它运作良好。

我无法弄清楚的另一件事是,如果我有一个没有孩子的根菜单项,我希望它有一个不同的输出,如

<a id="8">No Children Menu Item</a>
Instead of:
<a class="menuitem submenuheader">No Children Menu Item</a>

第二个例子会创建make,它会显示一点(+/-)用于展开和收缩,并且不允许我点击它。为了澄清<a>标签,我使用javascript根据id执行.get(),这就是没有显示href或url的原因。

更新

它工作正常,我把它发布在Github上,任何想要它的人。 https://github.com/ajhalls/php-accordian-menu

1 个答案:

答案 0 :(得分:1)

试试这个:

<?php
include 'db.php';

$sql = "SELECT * FROM menu_items WHERE status = 'ACTIVE' ORDER BY pid ASC, sortorder ASC, menu_item_name ASC";
$query = $db->query($sql);

$menu_items = array();

while($data = $query->fetch(PDO::FETCH_ASSOC)) {
    if($data['pid'] == 0) {
        $menu_items[$data['id']] = array();
        $menu_items[$data['id']]['id'] = $data['id'];
        $menu_items[$data['id']]['name'] = $data['menu_item_name'];
        $menu_items[$data['id']]['url'] = $data['menu_url'];
        $menu_items[$data['id']]['children'] = array();
    } else if($data['pid'] != 0) {
        $tmp = array();
        $tmp['id'] = $data['id'];
        $tmp['name'] = $data['menu_item_name'];
        $tmp['url'] = $data['menu_url'];

        array_push($menu_items[$data['pid']]['children'],$tmp);
        unset($tmp);
    }
}

function create_list($arr)
{
    $html = "";
    foreach($arr as $key => $value) {
        if(count($value['children']) > 0) {
            $html .= '  <a class="menuitem submenuheader" href="'. $value['url'] .'">'.$value['name'].'</a>
                        <div class="submenu">
                        <ul>';

            foreach($value['children'] AS $child) {
                $html .= '  <li>
                                <a id="'.$child['id'].'">'.$child['name'].'</a>
                            </li>';
            }

            $html .= '  </ul>
                        </div>';
        } else{
            $html .= '  <a id="'.$value['id'].'">'.$value['name'].'</a>';
        }
    }

    return $html;
}

echo "<div class=\"glossymenu\">";
    echo create_list($menu_items);
echo "</div>";
?>