<?php
// Select all entries from the menu table
$sql1 = $pardConfig->prepare("SELECT id, menu_title, menu_link, parent FROM pard_menu ORDER BY parent, sort, menu_title");
// Create a multidimensional array to conatin a list of items and parents
$sql1->execute();
$menu = array(
'items' => array(),
'parents' => array()
);
// Builds the array lists with data from the menu table
while ($items = $sql1->fetch()) {
// Creates entry into items array with current menu item id ie. $menu['items'][1]
$menu['items'][$items['id']] = $items;
// Creates entry into parents array. Parents array contains a list of all items with children
$menu['parents'][$items['parent']][] = $items['id'];
}
// Menu builder function, parentId 0 is the root
function buildMenu($pardConfig, $parent, $menu)
{
$html = "";
if (isset($menu['parents'][$parent])) {
$html .= "
<ul>\n";
foreach ($menu['parents'][$parent] as $itemId) {
if (!isset($menu['parents'][$itemId])) {
$html .= "<li>\n <a href='" . $menu['items'][$itemId]['menu_link'] . "'>" . $menu['items'][$itemId]['menu_title'] . "</a>\n</li> \n";
}
if (isset($menu['parents'][$itemId])) {
$html .= "
<li>\n <a href='" . $menu['items'][$itemId]['menu_link'] . "'>" . $menu['items'][$itemId]['menu_title'] . "</a> \n";
$html .= buildMenu($pardConfig, $itemId, $menu);
$html .= "</li> \n";
}
}
$html .= "</ul> \n";
}
return $html;
}
echo buildMenu($pardConfig, 0, $menu);
?>
上面的代码包含一个用于创建带有多级子菜单的动态菜单的php代码。我有预定义的类...
ul
(第一个UI),我有.nav
类li
,我有.dropdown
类
为李.dropdown-menu
元素有ul
个等级
它的父元素为li
.dropdown-submenu
类用于第三级子菜单所以我想修改我的代码,将4个setps添加到它?任何帮助将不胜感激?
我将使用bootsramp菜单API
我用Jquery做的方法就像bellow一样。但是100%不好......
$(".nav-collapse").find("ul").first().addClass("nav");
$(".nav-collapse").find("li").has("ul").addClass("nav");
$(".nav").find("li:has(ul) a").attr("data-toggle", "dropdown");
$('ul').filter(function () {
return $(this).parent().is('li')
}).addClass('dropdown-menu');
$(".nav").find("li ul li").addClass("dropdown-submenu");
$('.dropdown-toggle').dropdown();
});
答案 0 :(得分:4)
通过不使用对象来表示菜单元素,您自己难以使代码变得困难。正因为如此,并且因为您在渲染菜单结构的同时有效地构建菜单结构,您的代码难以阅读,难以思考,这就是您难以发现的原因让它做你想做的事。
重构代码以使用菜单元素的类完全将菜单的构建与渲染分开,并且更容易将明确的函数放入其中以决定如何渲染它。
class MenuElement {
var $parent = null;
var $children = array();
var $menuTitle;
var $menuLink;
function __construct($parent, $menuTitle, $menuLink){
$this->parent = $parent;
$this->menuTitle = $menuTitle;
$this->menuLink = $menuLink;
}
function hasParent(){
if ($this->parent) {
return true;
}
return false;
}
function addChild($child){
$this->children[] = $child;
}
function hasChildren(){
return count($children);
}
function hasGrandParent(){
if ($this->parent) {
return $this->parent->hasParent();
}
return false;
}
function render() {
$navClass = '';
$ulClass = '';
$liClass = '';
if ($this->parent == false) {
//For main ul (First Ul) i have .nav class
$navClass = 'nav';
}
if (count($this->children)){
//For any li where has first level sub menus i have .dropdown class for li
$liClass = 'dropdown';
}
if($this->parent) {
//Additionally for 2nd step i have .dropdown-menu class for
//ul elemnts which it has a parent element as a li
$ulClass = 'dropdown-menu';
}
if ($this->hasGrandParent() == true){
//And i have a .dropdown-submenu class for 3rd level sub menus
$ulClass = 'dropdown-submenu';
//$ulClass .= ' dropdown-submenu'; if you wanted both classes
}
$output = "<ul class='$navClass'>";
$output .= "<li class='$liClass'>";
$output .= "<a href='".$this->menuLink."'>".$this->menuTitle."</a>";
foreach ($this->children as $child) {
$output .= $child->render();
}
$output .= "</li>";
$output .= '</ul>';
return $output;
}
}
//Builds a menu and returns the root element of it.
function buildMenu(){
$rootElement = null;
// Select all entries from the menu table
$sql1 = $pardConfig->prepare("SELECT id, menu_title, menu_link, parent FROM pard_menu ORDER BY parent, sort, menu_title");
// Create a multidimensional array to conatin a list of items and parents
$sql1->execute();
$menuElements = array();
while ($items = $sql1->fetch()) {
$parent = null;
$parentID = $items['parent'];
if ($parentID) {
if(array_key_exists($parentID, $menuElements) == true) {
$parent = $menuElements[$parentID];
}
else{
throw \Exception("Tried to reference parent which doesn't exist");
}
}
$id = $items['id'];
$menuElements[$id] = new MenuElement($parent, $items['menu_title'], $items['menu_link']);
if ($id == 0) {
$rootElement = $menuElements[$id];
}
if ($parent) {
$parent->addChild($menuElements[$id]);
}
}
if ($rootElement == null) {
throw Exception("Root element not found, menu is borked");
}
//TODO - you may prefer to return $menuElements
return $rootElement;
}
$menu = buildMenu();
$output = $rootElement->render();
echo $output;
顺便说一下,这仍然是一个错误的代码,因为它混合了从数据库中检索菜单并构建它。最好将它们分开,以便您可以从您希望的任何数据源动态构建菜单。
同样,表中parent
的列名称会更好parentID
,因为这样可以避免$ parentID变量(ID为ID)和$ parent变量之间的混淆。对象
并且我没有调试过这个 - 答案只是为了说明如何做到这一点。