动态构建水平菜单

时间:2013-04-18 01:54:10

标签: php html mysql

我有这个JavaScript代码,允许我创建一个带有子菜单的水平菜单,如下所示:

<ul id="menu">
<li>Menu 1
  <ul>
   <li>Sub Menu 1</li>
  </ul>
</li>
</ul>

我可以根据需要创建任意数量的子菜单,问题是我使用PHP从MySQL数据库中获取链接,并且不知道如何动态构建这些子菜单而无需手动检查一遍又一遍子菜单。例如在MySQL表中:

字段: Menu_ID 菜单名 Menu_Link Menu_ParentID

因此菜单ID只是一个自动增量,而menu_parentid允许我将子菜单名称/链接分配给父菜单。但为了做到这一点,我目前正在进行2次子菜单检查:

$query = "SELECT * FROM site_menu WHERE Menu_ParentID = 0";

foreach($query AS $q)
{
//run through the results
$query2 = "SELECT * FROM site_menu WHERE Menu_ParentID = $q['id']";

foreach($query2 AS $q2)
{
//run through the results
}
}

正如你所看到的,我必须查询两次以获得第一个子菜单,如果有第三个子菜单怎么办?我必须运行3个查询吗?有什么建议吗?

6 个答案:

答案 0 :(得分:1)

也许函数或do..while循环可能是有序的?概念证明:

function menuQuery($id)
{
    $query = "SELECT * FROM site_menu WHERE Menu_ParentID = $id";

    if ($query) {
        foreach($query AS $q) {
            //run through the results
            menuQuery($q->id);
        }
    }
}

//initial call of top level menu items
menuQuery(0);

答案 1 :(得分:0)

我建议在菜单表中添加排序或订单列。然后,您可以使用排序列撤回所有结果。这将允许您订购菜单的顶级,子菜单项正好在彼此之下。

使用它可以创建一个包含数据库结果的循环,并根据是否填充了parent_id来选择要编写的菜单部分。

答案 2 :(得分:0)

  1. 撰写单个查询,按Menu_ParentID
  2. 排序
  3. 一次查询一行的过程。你将从root开始,因为它的ID是0.对于每一行,循环遍历所有其他行并找到该行的子节点,即父id等于你正在处理的行的id的那些行。使用此过程构建如下数据结构:

    [ Root Item 1, [Child1, Child2, [SubChild1, SubChild2], Child3], Root Item 2, ...]
    
  4. 编写一个这样的辅助函数(未经测试):

    function displayItem($item) {
      if (is_array($item)) {
        $html = '<li><ul>';
        foreach ($item as $subitem) $html .= displayItem($subItem);
        $html .= '</ul></li>';
        return $html;
      }
      else return '<li>' . $item . '</li>';
    }
    
  5. 遍历您在2.中创建的结构,为每个元素调用displayItem

答案 3 :(得分:0)

这是一个在数据库上只运行一次的例子,只是使用一个简单的递归函数,它可以分层次地引入数组。

# table
CREATE TABLE foo (
    menu_id int not null auto_increment primary key, 
    menu_name varchar(255) not null, 
    menu_link varchar(255) not null default '#',
    menu_parent_id int not null default 0
);

# data 
INSERT INTO `test`.`foo`
    (`menu_id`,`menu_name`,`menu_link`,`menu_parent_id`)
VALUES
    (1, 'Catalog', '#', 0),
    (2, 'Reports', '#', 0),
    (3, 'Products', '#', 1),
    (4, 'Sales', '#', 2),
    (5, 'Customers', '#', 2),
    (6, 'Tvs', '#', 3);

这是你的php代码:

<?php
$db = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '****');

$stmt = $db->query("SELECT * FROM foo");
$resultSet = $stmt->fetchAll(PDO::FETCH_ASSOC);


$setMenu = function ($data, $index = 0) use (&$setMenu){
                $menu = array();

        foreach ($data as $row) {
            if ((int) $row['menu_parent_id'] !== $index)
                continue;

            $menu[$row['menu_id']] = array(
                'name' => $row['menu_name'],
                'link' => $row['menu_link'],
                'submenus' => $setMenu($data, (int) $row['menu_id']),
            );
        }

        return $menu;
};

// your menu 
$menu = $setMenu($resultSet, 0);

var_export($menu);

它会为您提供准备进入列表的信息(ul)。

干杯!

答案 4 :(得分:0)

存储网站导航树的最佳技术称为Nested Set Model

这里有一个很好的示例实现:Dealing with nested sets in mysql?

答案 5 :(得分:0)

$data=array(
array('Menu_ID'=>1, 'Menu_Name'=>'Catalog', 'Menu_Link'=>'#', 'Menu_ParentID'=>0),
array('Menu_ID'=>2, 'Menu_Name'=>'Reports', 'Menu_Link'=>'#', 'Menu_ParentID'=>0),
array('Menu_ID'=>3, 'Menu_Name'=>'Products','Menu_Link'=> '#','Menu_ParentID'=> 1),
array('Menu_ID'=>4, 'Menu_Name'=>'Sales','Menu_Link'=> '#', 'Menu_ParentID'=>2),
array('Menu_ID'=>5, 'Menu_Name'=>'Customers','Menu_Link'=> '#', 'Menu_ParentID'=>2),
array('Menu_ID'=>6, 'Menu_Name'=>'Tvs','Menu_Link'=> '#','Menu_ParentID'=> 3));

print_r(loop_menu($data));

// Menu_ID Menu_Name Menu_Link Menu_ParentID
function loop_menu($rows,$parent = 0){
 $arr=array();
 $i=0;
  foreach ($rows as $row)
  { 
        if (array_key_exists('Menu_ParentID',$row) && $row['Menu_ParentID'] == $parent){

                if(array_key_exists($i,$arr)){
                    $arr[$i]=array();
                }
                $arr[$i]['data']=$row;
                $arr[$i]['child']= loop_menu($rows,$row['Menu_ID']);
                $i++;
        }
  }
    return $arr;
}

然后

Array
(
    [0] => Array
        (
            [data] => Array
                (
                    [Menu_ID] => 1
                    [Menu_Name] => Catalog
                    [Menu_Link] => #
                    [Menu_ParentID] => 0
                )

            [child] => Array
                (
                    [0] => Array
                        (
                            [data] => Array
                                (
                                    [Menu_ID] => 3
                                    [Menu_Name] => Products
                                    [Menu_Link] => #
                                    [Menu_ParentID] => 1
                                )

                            [child] => Array
                                (
                                    [0] => Array
                                        (
                                            [data] => Array
                                                (
                                                    [Menu_ID] => 6
                                                    [Menu_Name] => Tvs
                                                    [Menu_Link] => #
                                                    [Menu_ParentID] => 3
                                                )

                                            [child] => Array
                                                (
                                                )

                                        )

                                )

                        )

                )

        )

    [1] => Array
        (
            [data] => Array
                (
                    [Menu_ID] => 2
                    [Menu_Name] => Reports
                    [Menu_Link] => #
                    [Menu_ParentID] => 0
                )

            [child] => Array
                (
                    [0] => Array
                        (
                            [data] => Array
                                (
                                    [Menu_ID] => 4
                                    [Menu_Name] => Sales
                                    [Menu_Link] => #
                                    [Menu_ParentID] => 2
                                )

                            [child] => Array
                                (
                                )

                        )

                    [1] => Array
                        (
                            [data] => Array
                                (
                                    [Menu_ID] => 5
                                    [Menu_Name] => Customers
                                    [Menu_Link] => #
                                    [Menu_ParentID] => 2
                                )

                            [child] => Array
                                (
                                )

                        )

                )

        )

)

然后将类似数组的代码编译为ul

http://sandbox.onlinephpfunctions.com/code/2b3ab04f959413ebf75b65034edd60da61ed0020

更新

另一种数组样式

$arr[$i]['data'] = $row;
$arr[$i]['child']= loop_menu($rows,$row['Menu_ID']);

更改为

$row['child'] = loop_menu($rows,$row['Menu_ID']);
$arr[$i] = $row;

获取