分类动态菜单以添加特定类php

时间:2013-06-19 13:29:57

标签: php html css dynamic menu

 <?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代码。我有预定义的类...

  1. 对于主ul(第一个UI),我有.nav
  2. 对于任何具有第一级子菜单的li,我有.dropdown类 为李
  3. 另外,对于第二步,.dropdown-menu元素有ul个等级 它的父元素为li
  4. 我有一个.dropdown-submenu类用于第三级子菜单
  5. 所以我想修改我的代码,将4个setps添加到它?任何帮助将不胜感激?

    我将使用bootsramp菜单API

    TAKE A LOOK @ THIS

    我用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();
       });
    

1 个答案:

答案 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变量之间的混淆。对象

并且我没有调试过这个 - 答案只是为了说明如何做到这一点。