ОРИГИНАЛЬНЫЙ ПОЧТ
Я хочу создать меню навигации в PHP с помощью Bootstrap 4. Проблема в том, что один из <li> не подходит (тот, что из dropdown, он не раскрывается, а просто обычный nav-item). Этот код работает нормально, если вы хотите создать нормальное меню с <ul> и <li>, но для начальной загрузки вам необходимо иметь nav-item dropdown на <li> с идентификатором 2 с именем Dropdown. Как бы я это сделал?
Надеюсь, этой информации достаточно.
Это array ():
array (size=3)
0 =>
array (size=5)
0 =>
array (size=3)
'id' => string '1' (length=1)
'menu_naam' => string 'Home' (length=4)
'parent_id' => string '0' (length=1)
1 =>
array (size=3)
'id' => string '2' (length=1)
'menu_naam' => string 'Dropdown' (length=4)
'parent_id' => string '0' (length=1)
2 =>
array (size=3)
'id' => string '3' (length=1)
'menu_naam' => string 'Winkelwagen' (length=11)
'parent_id' => string '0' (length=1)
3 =>
array (size=3)
'id' => string '4' (length=1)
'menu_naam' => string 'Contact' (length=7)
'parent_id' => string '0' (length=1)
4 =>
array (size=3)
'id' => string '5' (length=1)
'menu_naam' => string 'Feedback' (length=8)
'parent_id' => string '0' (length=1)
2 =>
array (size=1)
0 =>
array (size=3)
'id' => string '6' (length=1)
'menu_naam' => string 'Sub Menu' (length=8)
'parent_id' => string '2' (length=1)
6 =>
array (size=1)
0 =>
array (size=3)
'id' => string '7' (length=1)
'menu_naam' => string 'Sub Sub Menu' (length=12)
'parent_id' => string '6' (length=1)
Это PHP, который я использую для создания меню:
<?php
function menu_builder() {
global $pdo;
$sql = $pdo->prepare("SELECT * FROM menus");
if ($sql->execute()) {
while ($row = $sql->fetch(PDO::FETCH_ASSOC)) {
$array[$row['parent_id']][] = $row;
}
loop_array($array);
}
}
function loop_array($array = array(), $parent_id = 0) {
if (!empty($array[$parent_id])) {
echo "<ul class=\"navbar-nav mr-auto\">";
foreach ($array[$parent_id] as $item) {
echo "<li class=\"nav-item\">";
echo "<a href=\"#\" class=\"nav-link\">" . $item['menu_naam'] . "</a>";
loop_array2($array, $item['id']);
echo "</li>";
}
echo "</ul>";
}
}
function loop_array2($array = array(), $parent_id = 0) {
if (!empty($array[$parent_id])) {
echo "<li class=\"nav-item dropdown\">";
foreach ($array[$parent_id] as $item) {
echo "<a href=\"#\" class=\"nav-link dropdown-toggle\" id=\"navbarDropdown\" role=\"button\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\">" . $item['menu_naam'] . "</a>";
loop_array3($array, $item['id']);
}
echo "</li>";
}
}
function loop_array3($array = array(), $parent_id = 0) {
if (!empty($array[$parent_id])) {
echo "<div class=\"dropdown-menu\" aria-labelledby=\"navbarDropdown\">";
foreach ($array[$parent_id] as $item) {
echo "<a class=\"dropdown-item\" href=\"#\">" . $item['menu_naam'] . "</a>";
}
echo "</div>";
}
}
Я действительно надеюсь, что кто-то может мне помочь с этим, следует ли мне добавить что-то в базу данных, чтобы он знал, что это раскрывающийся список? Я думаю, что мой код слишком большой и сложный, должен быть более простой способ, но я не знаю, как это сделать. Думаю, мне нужен совершенно другой подход. Если бы ты только мог помочь мне в правильном направлении, это тоже было бы хорошо.
Также небольшая благодарность парню, который сделал учебник по подменю (здесь вы также можете увидеть, как меню построено с помощью <ul> и <li> и делает именно то, что ему нужно, но не для bootstrap): https://thewikihow.com/video_Ol63V4R-TdI
Обновлено: Я нашел здесь своего рода решение: Динамическое меню php bootstrap mysql
Что у меня сейчас есть:
function drawMenu($pdo, $parent_id, $level = null) {
$sql = $pdo->prepare("SELECT * FROM menus where parent_id = $parent_id");
$sql->execute();
foreach ($sql->fetchAll() as $row) {
$sql = $pdo->prepare("SELECT count(*) FROM menus where parent_id = " . $row['id'] . "");
$sql->execute();
// The item is parent, so do recursion again
//var_dump($sql->fetchAll()[0][0]);
if ($sql->fetchAll()[0][0] !== '0' && $level !== 0){
echo "<li class=\"nav-item dropdown\"><a href=\"" . $row['url'] . "\" class=\"nav-link dropdown-toggle\" id=\"navbarDropdownMenuLink\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\">" . $row['menu_naam'] . "</a><div class=\"dropdown-menu\" aria-labelledby=\"navbarDropdownMenuLink\">\n";
drawMenu($pdo, $row[0], $level - 1);
echo "</div></li>\n";
}
else { // The item is a leaf or we reach the end level, i.e. base case, so do print the item label
echo "<li class=\"nav-item\"><a href=\"#\" class=\"nav-link\">" . $row['menu_naam'] . "</a></li>\n";
}
}
}
?>
<header class = "navbar navbar-dark bg-dark fixed-top navbar-expand-sm">
<a class = "navbar-brand" href = "#">Webshop</a>
<button class = "navbar-toggler" style = "background: #000000" type = "button" data-toggle = "collapse" data-target = "#navbar-header" aria-controls = "navbar-header">
☰
</button>
<div class = "navbar-collapse collapse show" id = "navbar-header">
<ul class = "navbar-nav mr-auto">
<?php
drawMenu($pdo, 0, null);
?>
</ul>
</div>
</header>
Но проблема в том, что он печатает несколько
<div class = "dropdown-menu" aria-labelledby = "navbarDropdownMenuLink">
HTML теперь выглядит так:
<div class = "navbar-collapse collapse show" id = "navbar-header">
<ul class = "navbar-nav mr-auto">
<li class = "nav-item"><a href = "#" class = "nav-link"><span class = "fas fa-home"></span> Home</a></li>
<li class = "nav-item dropdown"><a href = "#" class = "nav-link dropdown-toggle" id = "navbarDropdownMenuLink" data-toggle = "dropdown" aria-haspopup = "true" aria-expanded = "false">Dropdown</a><div class = "dropdown-menu" aria-labelledby = "navbarDropdownMenuLink">
<li class = "nav-item dropdown"><a href = "#" class = "nav-link dropdown-toggle" id = "navbarDropdownMenuLink" data-toggle = "dropdown" aria-haspopup = "true" aria-expanded = "false">Sub Menu</a><div class = "dropdown-menu" aria-labelledby = "navbarDropdownMenuLink">
<li class = "nav-item"><a href = "#" class = "nav-link">Sub-sub Menu</a></li>
</div></li>
</div></li>
<li class = "nav-item"><a href = "#" class = "nav-link"><span class = "fas fa-shopping-cart"> </span> Winkelwagen</a></li>
<li class = "nav-item"><a href = "#" class = "nav-link">Contact</a></li>
<li class = "nav-item"><a href = "#" class = "nav-link">Feedback</a></li>
</ul>
</div>






Я добавил menu в базу данных и проверил, 0 или 1. Я удалил подменю, но обновлю этот пост, если добавлю их.
function menu_builder($pdo, $parent_id) {
$sql = $pdo->prepare("SELECT * FROM menus");
if ($sql->execute()) {
while ($row = $sql->fetch(PDO::FETCH_ASSOC)) {
$array[$row['parent_id']][] = $row;
}
main_menu($array);
}
}
function main_menu ($array, $parent_id = 0) {
if (!empty($array[$parent_id])) {
foreach ($array[$parent_id] as $item) {
if ($item['menu'] == '0') {
echo " <li class=\"nav-item\">" . PHP_EOL;
echo " <a class=\"nav-link\" href=\"#\">" . $item['menu_naam'] . "</a>" . PHP_EOL;
main_menu($array, $item['id']);
echo " </li>" . PHP_EOL;
}
elseif ($item['menu'] == '1') {
echo " <li class=\"nav-item dropdown\"><a class=\"nav-link dropdown-toggle\" href=\"#\" id=\"navbarDropdown\" role=\"button\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\">" . $item['menu_naam'] . "</a>" . PHP_EOL;
sub_menu($array, $item['id']);
echo " </li>" . PHP_EOL;
}
}
//echo "</div>" . PHP_EOL;
echo "</li>" . PHP_EOL;
}
}
function sub_menu ($array, $parent_id) {
if (!empty($array[$parent_id])) {
echo " <div class=\"dropdown-menu\" aria-labelledby=\"navbarDropdown\">" . PHP_EOL;
foreach ($array[$parent_id] as $item) {
echo " <a class=\"dropdown-item\" href=\"" . $item['url'] . "\">" . $item['menu_naam'] . "</a>" . PHP_EOL;
}
echo " </div>" . PHP_EOL;
}
}
?>
<header class = "navbar navbar-dark bg-dark fixed-top navbar-expand-sm">
<a class = "navbar-brand" href = "#">Webshop</a>
<button class = "navbar-toggler" style = "background: #000000" type = "button" data-toggle = "collapse" data-target = "#navbar-header" aria-controls = "navbar-header">
☰
</button>
<div class = "navbar-collapse collapse show" id = "navbar-header">
<?php
echo "<ul class=\"navbar-nav mr-auto\">";
echo menu_builder($pdo, 0);
echo "</ul>" . PHP_EOL;
?>
</div>
</header>
РЕДАКТИРОВАТЬ: чтобы иметь подменю, код выглядит так, и вам также понадобится следующий css.
function menu_builder($pdo, $parent_id) {
$sql = $pdo->prepare("SELECT * FROM menus");
if ($sql->execute()) {
while ($row = $sql->fetch(PDO::FETCH_ASSOC)) {
$array[$row['parent_id']][] = $row;
}
main_menu($array);
}
}
function main_menu ($array, $parent_id = 0) {
if (!empty($array[$parent_id])) {
foreach ($array[$parent_id] as $item) {
if ($item['menu'] == '0') {
echo " <li class=\"nav-item\">" . PHP_EOL;
echo " <a class=\"nav-link\" href=\"" . $item['url'] . "\">" . $item['menu_naam'] . "</a>" . PHP_EOL;
main_menu($array, $item['id']);
echo " </li>" . PHP_EOL;
}
elseif ($item['menu'] == '1') {
echo " <li class=\"nav-item dropdown\">". PHP_EOL;
echo " <a class=\"nav-link dropdown-toggle\" href=\"" . $item['url'] . "\" id=\"navbarDropdown\" role=\"button\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\">" . $item['menu_naam'] . "</a>" . PHP_EOL;
sub_menu($array, $item['id']);
echo " </li>" . PHP_EOL;
}
}
}
}
function sub_menu ($array, $parent_id) {
if (!empty($array[$parent_id])) {
echo " <div class=\"dropdown-menu\" aria-labelledby=\"navbarDropdown\">" . PHP_EOL;
foreach ($array[$parent_id] as $item) {
if ($item['sub_menu'] == '0') {
echo " <a class=\"dropdown-item\" href=\"" . $item['url'] . "\">" . $item['menu_naam'] . "</a>" . PHP_EOL;
}
elseif ($item['sub_menu'] == '1') {
echo " <div class=\"dropdown-submenu\">" . PHP_EOL;
echo " <a class=\"dropdown-item dropdown-toggle\" href=\"" . $item['url'] . "\">" . $item['menu_naam'] . "</a>" . PHP_EOL;
sub_sub_menu($array, $item['id']);
echo " </div>" . PHP_EOL;
}
}
echo " </div>" . PHP_EOL;
}
}
function sub_sub_menu ($array, $parent_id) {
if (!empty($array[$parent_id])) {
echo " <div class=\"dropdown-menu\" aria-labelledby=\"navbarDropdown\">" . PHP_EOL;
foreach ($array[$parent_id] as $item) {
echo " <a class=\"dropdown-item\" href=\"" . $item['url'] . "\">" . $item['menu_naam'] . "</a>" . PHP_EOL;
}
}
echo " </div>" . PHP_EOL;
}
CSS, который вам нужен для подменю, потому что бутстрап не поддерживает его по умолчанию (https://stackoverflow.com/a/45755948/2877035):
.dropdown-submenu {
position: relative;
}
.dropdown-submenu a::after {
transform: rotate(-90deg);
position: absolute;
right: 6px;
top: .8em;
}
.dropdown-submenu .dropdown-menu {
top: 0;
left: 100%;
margin-left: .1rem;
margin-right: .1rem;
}
и jQuery:
$('.dropdown-menu a.dropdown-toggle').on('click', function(e) {
if (!$(this).next().hasClass('show')) {
$(this).parents('.dropdown-menu').first().find('.show').removeClass("show");
}
var $subMenu = $(this).next(".dropdown-menu");
$subMenu.toggleClass('show');
$(this).parents('li.nav-item.dropdown.show').on('hidden.bs.dropdown', function(e) {
$('.dropdown-submenu .show').removeClass("show");
});
return false;
});
Я внес некоторые изменения в bootstrap 4.1.
<style type = "text/css">
.navbar .dropdown-toggle, .navbar .dropdown-menu a {
cursor: pointer;
}
.navbar .dropdown-item.active, .navbar .dropdown-item:active {
color: inherit;
text-decoration: none;
background-color: inherit;
}
.navbar .dropdown-item:focus, .navbar .dropdown-item:hover {
color: #16181b;
text-decoration: none;
background-color: #f8f9fa;
}
@media (min-width: 767px) {
.navbar .dropdown-toggle:not(.nav-link)::after {
display: inline-block;
width: 0;
height: 0;
margin-left: .5em;
vertical-align: 0;
border-bottom: .3em solid transparent;
border-top: .3em solid transparent;
border-left: .3em solid;
}
}
</style>
<script type = "text/javascript">
$(document).ready(function () {
$('.navbar .dropdown-item').on('click', function (e) {
var $el = $(this).children('.dropdown-toggle');
var $parent = $el.offsetParent(".dropdown-menu");
$(this).parent("li").toggleClass('open');
if (!$parent.parent().hasClass('navbar-nav')) {
if ($parent.hasClass('show')) {
$parent.removeClass('show');
$el.next().removeClass('show');
$el.next().css({"top": -999, "left": -999});
} else {
$parent.parent().find('.show').removeClass('show');
$parent.addClass('show');
$el.next().addClass('show');
$el.next().css({"top": $el[0].offsetTop, "left": $parent.outerWidth() - 4});
}
e.preventDefault();
e.stopPropagation();
}
});
$('.navbar .dropdown').on('hidden.bs.dropdown', function () {
$(this).find('li.dropdown').removeClass('show open');
$(this).find('ul.dropdown-menu').removeClass('show open');
});
});
</script>
<?php function menu_builder1($db, $parent_id) {
$sql = $db->prepare("SELECT * FROM menu WHERE status = 1 ORDER BY position ASC");
if ($sql->execute()) {
while ($row = $sql->fetch(PDO::FETCH_ASSOC)) {
$array[$row['menu_sub_id']][] = $row;
}
main_menu1($array);
}
}
function main_menu1($array, $parent_id = false) {
if (!empty($array[$parent_id])) {
foreach ($array[$parent_id] as $item) {
if ($item['dropdown'] == false) {
echo '<li class = "nav-item active"><a class = "nav-link" href = "' . $item['href'] . '">' . $item['name'] . '</a></li>';
}
elseif ($item['dropdown'] == true) {
echo '<li class = "nav-item dropdown"><a class = "nav-link dropdown-toggle" id = "dropdown2" data-toggle = "dropdown" aria-haspopup = "true" aria-expanded = "false">' . $item['name'] . '</a>';
sub_menu1($array, $item['menu_id']);
echo '</li>';
}
}
}
}
function sub_menu1($array = array(), $parent_id = false) {
if (!empty($array[$parent_id])) {
echo '<ul class = "dropdown-menu" aria-labelledby = "dropdown2">';
foreach ($array[$parent_id] as $item) {
if ($item['dropdown'] == false) {
echo '<li class = "dropdown-item"><a href = "' . $item['href'] . '">' . $item['name'] . '</a></li>';
}
elseif ($item['dropdown'] == true) {
echo '<li class = "dropdown-item dropdown"><a class = "dropdown-toggle" id = "dropdown2-1" data-toggle = "dropdown" aria-haspopup = "true" aria-expanded = "false">' . $item['name'] . '</a>';
sub_sub_menu1($array, $item['menu_id']);
echo '</li>';
}
}
echo "</ul>";
}
}
function sub_sub_menu1($array = array(), $parent_id = false) {
if (!empty($array[$parent_id])) {
echo '<ul class = "dropdown-menu" aria-labelledby = "dropdown2-1">';
foreach ($array[$parent_id] as $item) {
if ($item['dropdown'] == false) {
echo '<li class = "dropdown-item"><a href = "' . $item['href'] . '">' . $item['name'] . '</a></li>';
}
}
echo "</ul>";
}
}
?>
<div class = "navbar navbar-expand-md navbar-dark bg-dark mb-4" role = "navigation">
<button class = "navbar-toggler" type = "button" data-toggle = "collapse" data-target = "#navbarCollapse" aria-controls = "navbarCollapse" aria-expanded = "false" aria-label = "Toggle navigation">
<span class = "navbar-toggler-icon"></span>
</button>
<div class = "collapse navbar-collapse" id = "navbarCollapse">
<ul class = "navbar-nav mr-auto">
<?=menu_builder1($db, 0)?>
</ul>
</div>
</div>
также некоторая информация по SQL
CREATE TABLE `menu` (
`menu_id` int(11) NOT NULL,
`menu_sub_id` int(11) NOT NULL,
`added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`status` int(1) NOT NULL DEFAULT '1',
`href` varchar(150) NOT NULL,
`class` varchar(150) NOT NULL,
`position` int(3) NOT NULL,
`name` varchar(150) NOT NULL,
`description` varchar(500) NOT NULL,
`dropdown` int(11) NOT NULL,
`sub_menu` int(1) NOT NULL,
`sub_sub_menu` int(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `menu`
ADD PRIMARY KEY (`menu_id`);
ALTER TABLE `menu`
MODIFY `menu_id` int(11) NOT NULL AUTO_INCREMENT;
COMMIT;