-1

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

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

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

字段:Menu_ID Menu_Name 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 个查询吗?有什么建议么?

4

6 回答 6

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);
于 2013-04-18T02:11:41.507 回答
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;

得到

于 2013-04-18T04:43:45.607 回答
0
  1. 编写一个查询,按顺序排列Menu_ParentID
  2. 处理一次查询一行。您将从根开始,因为它的 ID 为 0。对于每一行,遍历所有其他行并找到该行的子行,即父 ID 等于您正在处理的行的 ID 的那些行。使用此过程构建数据结构,如下所示:

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

    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>';
    }
    
  4. 循环遍历您在 2. 中创建的结构,为每个元素调用 displayItem

于 2013-04-18T02:22:02.300 回答
0

存储网站导航树的最佳技术称为嵌套集模型

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

于 2013-04-18T04:16:24.630 回答
0

我建议在您的菜单表中放置一个排序或排序列。然后,您可以使用排序列拉回所有结果。这将允许您订购菜单的顶层,子菜单项位于彼此下方。

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

于 2013-04-18T02:01:01.837 回答
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)的信息。

干杯!

于 2013-04-18T04:02:02.693 回答