2
 <?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(最初のUl)には.navクラスがあります
  2. li最初のレベルのサブメニューがある場所には、.dropdownli のクラスがあります
  3. さらに、2番目のステップでは、親要素を持つ要素の.dropdown-menuクラスがありますulli
  4. そして、私は.dropdown-submenu第3レベルのサブメニューのクラスを持っています

だから私はそれにそれらの4セットを追加して私のコードを変更したいですか?何か助けていただければ幸いです。

これにはブートランプ メニュー API を使用します。

これを見てみよう

このアプローチは、次のようにJqueryで行いましたが、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();
   });
4

1 に答える 1

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) とオブジェクトである $parent 変数の間の混乱を防ぐため、より適切です。

いいえ、私はこれをデバッグしていません-答えは、それがどのように行われるかを示すことです.

于 2013-06-21T15:17:36.093 に答える