我有这个JavaScript代码,它允许我创建一个带有子菜单的水平菜单,比如:
<ul id="menu">
<li>Menu 1
<ul>
<li>Sub Menu 1</li>
</ul>
</li>
</ul>
我可以创建任意多的子菜单,问题是我使用PHP从MySQL数据库中获取链接,不知道如何在不手动反复检查子菜单的情况下动态构建这些子菜单。例如MySQL表中的
字段:菜单_ID菜单名称菜单链接菜单_家长ID
因此,菜单ID只是一个自动增量,menu_parentid允许我为父菜单分配子菜单名称/链接。但为了做到这一点,我目前对两个子菜单进行检查:
$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个查询吗?有什么建议吗?
可能是一个函数或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);
我建议在菜单表中放一个排序或排序列。然后,您可以使用排序列收回所有结果。这将允许您订购菜单的顶层,子菜单项位于彼此的正下方。
这样,您就可以使用数据库结果创建一个循环,并根据parent_id是否填充来选择要写入菜单的哪个部分。
- 编写单个查询,按
Menu_ParentID
排序 -
一次处理一行查询。您将从根开始,因为它的ID为0。对于每一行,循环遍历所有其他行,找到该行的子行,即父id等于正在处理的行的id的行。使用这个过程来构建这样的数据结构:
[ Root Item 1, [Child1, Child2, [SubChild1, SubChild2], Child3], Root Item 2, ...]
-
编写一个类似的辅助函数(未经测试(:
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>'; }
-
循环遍历您在2.中创建的结构,为每个元素调用displayItem
存储网站导航树的最佳技术称为嵌套集模型。
这里有一个很好的实现示例:处理mysql中的嵌套集?
$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;
获取
这里有一个例子,它只在数据库上运行一次,只使用一个简单的递归函数,就可以分层地生成数组。
# 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(。
干杯!