问题
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