Build a bootstrap drop-down multi-level menu from a PHP array

对着背影说爱祢 提交于 2021-01-28 04:06:36

问题


I'm trying to make a bootstrap drop-down menu from an array in PHP.

I have written a recursive menu function, but I am struggling with adding the custom html attributes required for bootstrap.

My menu array is in the following format:

$menu = array(
   'calendar' => array(
      'text'   => 'Calendar',
      'rights' => 'user'
   ),
   'customers' => array(
      'text'   => 'Customers',
      'rights' => 'user',
      'sub' => array(
         'create-new' => array(
            'text'   => 'Create new customer',
            'rights' => 'user'
         ),
         'show-customers' => array(
            'text'   => 'Show all customers',
            'rights' => 'user'
         )
      )
   )
);

And the PHP to build the menu from an array as above:

function buildMenu($menu_array, $is_sub=FALSE) {

   $attr = (!$is_sub) ? ' id="menu"' : ' class="submenu"';
   $menu = "<ul".$attr.">";

   foreach($menu_array as $id => $properties) {
      foreach($properties as $key => $val) {
         if(is_array($val)) {
            $sub = buildMenu($val, TRUE);
         }
         else {
            $sub = NULL;
            $$key = $val;
         }
      }
      if(!isset($url)) {
         $url = $id;
      }
      $menu .= "<li><a href=".$url.">".$text."</a>".$sub."</li>";
      unset($url, $text, $sub);
   }

   return $menu . "</ul>";
}

echo $output = buildMenu($menu);

My desired output is:

<ul class="nav navbar-nav">
    <li><a href="#">Calendrier</a></li>
    <li class="dropdown">
        <a href="#" class="dropdown-toggle" data-toggle="dropdown">Customers <span class="caret"></span></a>
        <ul class="dropdown-menu">
            <li><a href="#">Create new customer</a></li>
            <li><a href="#">Show all customers</a></li>
        </ul>
    </li>
</ul>

回答1:


Your menu function was working for me, but the menu's html attributes needed some alteration:

<?php
function buildMenu(array $menu_array, $is_sub=FALSE)
{
   $ul_attrs = $is_sub ? 'class="dropdown-menu"' : 'class="nav navbar-nav"';
   $menu = "<ul $ul_attrs>";

   foreach($menu_array as $id => $attrs) {
      $sub = isset($attrs['sub']) 
         ? buildMenu($attrs['sub'], TRUE) 
         : null;
      $li_attrs = $sub ? 'class="dropdown"' : null;
      $a_attrs  = $sub ? 'class="dropdown-toggle" data-toggle="dropdown"' : null;
      $carat    = $sub ? '<span class="caret"></span>' : null;
      $menu .= "<li $li_attrs>";
      $menu .= "<a href='$id' $a_attrs>${attrs['text']}$carat</a>$sub";
      $menu .= "</li>";
   }

   return $menu . "</ul>";
}

You could pass in a parent path segment instead of the $is_sub boolean to construct url paths, or add the urls explicitly to the menu array and adjust accordingly.




回答2:


can you clarify on not being able to echo the sub menu? you mean: - 1st level shows up but the 2nd no does not - nothing shows up :) - or you're just not sure how to edit your code to achieve desired output ?

I'm asking because things display for me using your script as:

<?php

$menu = array(
   'calendar' => array(
      'text'   => 'Calendar',
      'rights' => 'user'
   ),
   'customers' => array(
      'text'   => 'Customers',
      'rights' => 'user',
      'sub' => array(
         'create-new' => array(
            'text'   => 'Create new customer',
            'rights' => 'user'
         ),
         'show-customers' => array(
            'text'   => 'Show all customers',
            'rights' => 'user'
         )
      )
   )
);

buildMenu($menu);

function buildMenu($menu_array, $is_sub=FALSE) {

   $attr = (!$is_sub) ? ' id="menu"' : ' class="submenu"';
   $menu = "<ul".$attr.">";

   foreach($menu_array as $id => $properties) {
      foreach($properties as $key => $val) {
         if(is_array($val)) {
            $sub = buildMenu($val, TRUE);
         }
         else {
            $sub = NULL;
            $$key = $val;
         }
      }
      if(!isset($url)) {
         $url = $id;
      }
      $menu .= "<li><a href=".$url.">".$text."</a>".$sub."</li>";
      unset($url, $text, $sub);
   }

   return $menu . "</ul>";
}

echo $output = buildMenu($menu);
 ?>

works fine for me, but the result (adding tabs/new lines) is more like

<ul id="menu">
    <li><a href=calendar>Calendar</a></li>
    <li>
        <a href=customers>Customers</a>
        <ul class="submenu">
            <li><a href=create-new>Create new customer</a></li>
            <li><a href=show-customers>Show all customers</a></li>
       </ul>
    </li>
</ul>



回答3:


I went ahead and added the url attribute to your arrays, so the array looks like this:

$menu = array(
   'calendar' => array(
      'text'   => 'Calendar',
      'rights' => 'user',
      'url'    => '#' 
   ),  
   'customers' => array(
      'text'   => 'Customers',
      'rights' => 'user',
      'sub' => array(
         'create-new' => array(
            'text'   => 'Create new customer',
            'rights' => 'user',
            'url'    => '#' 
         ),
         'show-customers' => array(
            'text'   => 'Show all customers',
            'rights' => 'user',
            'url'    =>  '#' 
         )   
      )   
   )   
);

And then modified the code. There are quite a few changes, the most notable being that you don't need to loop over every key => value pair in the array--since you know what they're going to be named, you can just access them (I'm operating under the assumption that your submenu will always have a key called "sub", correct me if I'm wrong). The final code I came up with, assuming that your key names are going to consistently be 'text', 'url' and 'sub' is this:

function buildMenu($menu_array, $is_sub=FALSE) {

   $attr = (!$is_sub) ? ' class="nav navbar-nav' : ' class="dropdown-menu"';
   $menu = "<ul".$attr.">";

   foreach($menu_array as $menu_item) {

     //set our link text
     $text = $menu_item['text'];

     //if we have a submenu
     if(isset($menu_item['sub'])) {

        //construct the submenu
        $sub = buildMenu($menu_item['sub'], TRUE);

        //give our li the appropriate class
        $li_class = 'class="dropdown"';

        //we don't need a real url for a dropdown
        $url = '#';

        //set up our additional anchor attributes
        $additional_attr = 'class="dropdown-toggle" data-toggle="dropdown"';
     } else {
        //no submenu
        $sub = '';

        //no li class needed
        $li_class = '';

        //assign our url (if it exists)
        $url = isset($menu_item['url']) ? $menu_item['url'] : '';

        //no additional attributes needed for our anchor tag
        $additional_attr = '';
     }

     //construct the whole thing
     $menu .= "<li $li_class><a href='".$url." '" . $additional_attr . ">".$text."</a>".$sub."</li>";
   }

which gives me the output of:

<ul class="nav navbar-nav>
    <li ><a href='#'>Calendar</a></li>
    <li class="dropdown">
        <a href='#' class="dropdown-toggle" data-toggle="dropdown">Customers</a>
        <ul class="dropdown-menu">
            <li ><a href='#'>Create new customer</a></li>
            <li ><a href='#'>Show all customers</a></li>
        </ul>
    </li>
</ul>



回答4:


This is a three-level bootstrap dropdown menu:

<?php
$menu = array(
    'link1' => array(
        'text'      => 'Link1',
    ),
    'link2' => array(
        'text'      => 'Link2',
        'sub_link2' => array(
            'sub_link2-1'   => array(
                'text'      => 'Sub_Link2',
            ),
        )
    ),
    'link3' => array(
        'text' => 'Link3',
        'sub_link3' => array(
            'sub_link3-1'   => array(
                'text'      => 'Sub_Link3',
            ),
            'sub_link4-1'   => array(
                'text'      => 'Sub_Link4',
                'sub_link4' => array(
                    'sub_link_4-1'  => array(
                        'text'      => 'Sub_Link_4-1',
                    ),
                    'sub_link_4-2'  => array(
                        'text'      => 'Sub_Link_4-2',
                    )
                )
            )
        )
    )
);

build_menu($menu);

function build_menu($menu_array, $is_sub = false)
{
    $attr = $is_sub ? ' class="dropdown-menu"' : ' class="nav navbar-nav"';
    $menu .= '<ul' . $attr . '>';

    foreach($menu_array as $id => $properties)
    {
        foreach($properties as $key => $val)
        {
            if(is_array($val))
            {
                $sub = build_menu($val, true);
            }
            else
            {
                $sub = NULL;
                $$key = $val;
            }
        }
        if(!isset($url))
        {
            $url = $id;
        }

        $li_class = ($is_sub && $sub) ? ' class="dropdown-submenu"' : '';
        $a_class = $sub ? 'class="dropdown-toggle" data-toggle="dropdown"' : '';
        $carret = ($sub && !$li_class) ? ' <i class="caret"></i>' : '';
        $menu .= '<li' . $li_class . '><a ' . $a_class . ' href="' . $url . '">'. $text . '' . $carret . '</a>' . $sub . '</li>';
        unset($url, $text, $sub);
    }

    $menu .= '</ul>';
    return $menu;
}

?>

And in html output:

    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
        <?php
            echo $output = build_menu($menu);
        ?>
    </div>

This html-code is generated:

<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
    <ul class="nav navbar-nav">
        <li><a  href="link1">Link1</a></li>
        <li><a class="dropdown-toggle" data-toggle="dropdown" href="link2">Link2 <i class="caret"></i></a>
            <ul class="dropdown-menu">
                <li><a  href="sub_link2-1">Sub_Link2</a></li>
            </ul>
        </li>
        <li><a class="dropdown-toggle" data-toggle="dropdown" href="link3">Link3 <i class="caret"></i></a>
            <ul class="dropdown-menu">
                <li><a  href="sub_link3-1">Sub_Link3</a></li>
                <li class="dropdown-submenu">
                    <a class="dropdown-toggle" data-toggle="dropdown" href="sub_link4-1">Sub_Link4</a>
                    <ul class="dropdown-menu">
                        <li><a  href="sub_link_4-1">Sub_Link_4-1</a></li>
                        <li><a  href="sub_link_4-2">Sub_Link_4-2</a></li>
                    </ul>
                </li>
            </ul>
        </li>
    </ul>
</div>



回答5:


mysql table structure as below

SN-ID-Title-Link-ParentID-User
01-400-Search-#-0-zaman
02-100-Admin-#-0-zaman

how i add it in array



来源:https://stackoverflow.com/questions/35527414/build-a-bootstrap-drop-down-multi-level-menu-from-a-php-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!