Вопрос или проблема
Как мне смешать типы HTML-элементов для навигационной панели с двумя меню?
Я создаю тему WordPress с Bootstrap 4.
Содержимое меню WordPress должно извлекаться из параметров меню, выводиться в навигационной панели Bootstrap 4. Я использую этот специальный для Bootstrap 4 wp_nav_menu
navwalker …
require_once get_template_directory() . '/inc/bs4navwalker.php';
… чтобы вывести основное меню текстовых ссылок навигации в виде ненумерованного списка, так как Бог задумал…
<!-- Navbar https://getbootstrap.com/docs/4.1/components/navbar/ -->
<nav class="navbar navbar-expand-md navbar-light"><!-- collapse at stated breakpoint -->
<a class="navbar-brand" href="https://wordpress.stackexchange.com/questions/311941/<?php echo esc_url( home_url("https://wordpress.stackexchange.com/" ) ); ?>">
<img src="https://www.example.com/logo.gif" height="30" class="d-inline-block align-top mr-1">
<?php bloginfo( 'name' ); ?>
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#bs4navbar" aria-controls="bs4navbar" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<?php
wp_nav_menu([ // bs4navwalker menu generator
'menu' => 'primary', // имя меню WordPress
'theme_location' => 'primary',
'depth' => 2,
// <nav>:
// 'container' => 'false',
'container_id' => 'bs4navbar',
'container_class' => 'collapse navbar-collapse',
// <ul>:
'menu_id' => false,
'menu_class' => 'navbar-nav ml-auto',
// другое:
'fallback_cb' => 'bs4navwalker::fallback',
'walker' => new bs4navwalker()
]);
?>
<button class="btn btn-outline-primary mx-3" type="submit">Кнопка</button>
<button class="btn btn-primary ml-3" type="submit">Записаться</button>
</nav>
Это работает отлично. Вывод…
<nav class="navbar navbar-expand-md navbar-light"><!-- collapse at stated breakpoint -->
<a class="navbar-brand" href="http://www.example.com/">
<img src="https://www.example.com/logo.gif" height="30" class="d-inline-block align-top mr-1">
Песочница </a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#bs4navbar" aria-controls="bs4navbar" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div id="bs4navbar" class="collapse navbar-collapse">
<ul id="menu-my-menu" class="navbar-nav ml-auto">
<li id="menu-item-3" class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item current_page_item menu-item-home menu-item-3 nav-item mx-3 active"><a title="Главная страница" href="http://sandbox.contexthq.com/" class="nav-link active" aria-expanded="false"><i class="icon-speedometer"></i>Главная</a></li>
<li id="menu-item-4" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-4 nav-item mx-3"><a title="Пример страницы" href="http://example.com/" class="nav-link" aria-expanded="false"><i class="ti-layout-grid2"></i>Тренды</a></li>
<li id="menu-item-5" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-5 nav-item mx-3"><a title="Пользовательская страница" href="http://example.com/custom/" class="nav-link" aria-expanded="false"><i class="ti-palette"></i>Пользовательская</a></li>
<li id="menu-item-14" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-14 nav-item mx-3"><a href="#" class="nav-link" aria-expanded="false">Стратегия</a></li>
</ul>
</div>
<button class="btn btn-outline-primary mx-3" type="submit">Кнопка</button>
<button class="btn btn-primary ml-3" type="submit">Записаться</button>
</nav>
Тем не менее, вы увидите часть, в которой я вручную вставил два <button>
элемента. Вместо жесткого кода я хочу, чтобы они генерировались динамически из меню WordPress, так же как и меню primary
.
Я создал второе меню WordPress, buttons
. Вот здесь я разбираюсь…
Я могу вставить второй вызов wp_nav_menu
для buttons
, сразу после первого для primary
…
<?php
wp_nav_menu([ // генератор меню bs4navwalker
'menu' => 'buttons', // имя меню WordPress
'theme_location' => 'buttons',
'depth' => 2,
// <nav>:
// 'container' => 'false',
'container_id' => 'bs4navbar',
'container_class' => 'collapse navbar-collapse',
// <ul>:
'menu_id' => false,
'menu_class' => 'navbar-nav ml-auto',
// другое:
'fallback_cb' => 'bs4navwalker::fallback',
'walker' => new bs4navwalker()
]);
?>
… и элементы меню будут вставлены в нужное место.
Проблема в том, что эти элементы – <li>
внутри <ul>
, так же как и меню primary
…
Я предполагаю, что bs4navwalker настроен на вывод всех элементов wp_nav_menu
как элементов списка, или, может быть, это дело WordPress.
Как я могу сделать так, чтобы элементы из второго меню, buttons
, выводились с использованием другой HTML-структуры, вместо этого как элементы <button>
?
Следующее решение, хотя и требует дополнительной обработки PHP…
<?php
$options = array(
'echo' => false,
'theme_location' => 'buttons',
'items_wrap' => '%3$s',
'menu_class' => false,
'menu_id' => false,
'container' => 'false',
'container_class' => false,
'container_id' => false,
'before' => '<button class="btn btn-primary mx-3 d-none d-md-block" type="submit">',
'after' => '</button>'
);
$menu = wp_nav_menu($options);
$output = strip_tags($menu, '<button>');
echo preg_replace('/btn-primary/', 'btn-outline-primary', $output, 1);
?>
Это включает в себя:
- Удаление
<ul>
- Не создание контейнеров
- Оборачивание каждого элемента в тег
<button>
- Подавление вывода
- Удаление всех тегов (т.е.
<li>
), за исключением<button>
) - В последней части замена первого экземпляра класса
btn-primary
наbtn-outline-primary
, чтобы сохранить кнопки двух цветов.
Вот вывод…
<button class="btn btn-outline-primary mx-3 d-none d-md-block" type="submit">Кнопка</button>
<button class="btn btn-primary mx-3 d-none d-md-block" type="submit">Узнать больше</button>
Я бы предпочел установить классы цветов кнопок, используя собственную функциональность WordPress для установки классов элементов меню, а не жестко кодировать их здесь.
Есть ли способ сделать так, чтобы эти классы появлялись в элементе навигации, вместо использования preg_replace
, или этот метод не поддержит это?
Ответ или решение
Как использовать элементы кнопок для элементов меню WordPress
Создание адаптивного и функционального навигационного меню с использованием WordPress и Bootstrap 4 — это задача, которая требует координированного подхода как к дизайну, так и к коду. В данном руководстве мы рассмотрим, как динамически генерировать элементы меню в виде кнопок, вытаскивая их из настроек меню WordPress.
1. Реализация второго меню
Ваша цель состоит в том, чтобы создать второе меню (например, buttons
), элементы которого будут отображаться в виде кнопок вместо стандартных ссылок. Начнем с его создания в админ-панели WordPress:
- Перейдите в
Внешний вид
->Меню
. - Создайте новое меню с именем
buttons
и добавьте нужные пункты.
2. Написание кода для отображения меню
Теперь вам нужно обновить файл темы (например, header.php
) для корректного отображения как основного меню, так и кнопочного меню.
Вот как можно это сделать:
<nav class="navbar navbar-expand-md navbar-light">
<a class="navbar-brand" href="<?php echo esc_url(home_url()); ?>">
<img src="https://www.example.com/logo.gif" height="30" class="d-inline-block align-top mr-1">
<?php bloginfo('name'); ?>
</a>
<!-- Кнопка для мобильной навигации -->
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#bs4navbar" aria-controls="bs4navbar" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<!-- Основное меню -->
<?php
wp_nav_menu([
'menu' => 'primary',
'theme_location' => 'primary',
'depth' => 2,
'container' => false,
'menu_class' => 'navbar-nav ml-auto',
'walker' => new bs4navwalker()
]);
?>
<!-- Динамическое кнопочное меню -->
<?php
$options = array(
'echo' => false,
'theme_location' => 'buttons',
'items_wrap' => '%3$s',
'menu_class' => false,
'menu_id' => false,
'container' => false,
'before' => '<button class="btn btn-primary mx-3" type="submit">',
'after' => '</button>'
);
// Получаем меню в виде кнопок
$menu = wp_nav_menu($options);
// Удаляем все теги, кроме <button>
$output = strip_tags($menu, '<button>');
echo $output;
?>
</nav>
3. Пояснение кода
- Регистрация второго меню: Убедитесь, что вы зарегистрировали оба меню в файле функций вашей темы (
functions.php
):
register_nav_menus([
'primary' => __('Primary Menu'),
'buttons' => __('Buttons Menu')
]);
- Dynamically Generated Buttons: Код, который мы использовали для кнопочного меню, позволяет оборачивать каждый элемент меню WordPress в тег
<button>
. Это делается с помощью параметровbefore
иafter
, которые добавляют классы Bootstrap, а также другие атрибуты.
4. Гибкость управления классами кнопок
Для того чтобы вам не приходилось жестко кодировать классы кнопок (такие как btn-primary
), их можно задавать в админ панели WordPress через настройки для каждого элемента меню. Однако, если это не поддерживается напрямую в WordPress, то можно добавить соответствующее поле для настройки классов в интерфейсе редактирования элементов меню, что позволит динамически генерировать стили кнопок:
add_filter('nav_menu_item_attributes', function($atts, $item) {
// Здесь можно добавить логику для установки классов кнопок
$atts['class'] = get_post_meta($item->ID, 'button_class', true);
return $atts;
}, 10, 2);
Заключение
Следуя предложенным шагам, вы сможете создать адаптивное меню с динамическими кнопками в вашей теме на WordPress, используя Bootstrap 4. Это не только улучшит пользовательский интерфейс вашего сайта, но и облегчит управление меню через админ-панель WordPress.
Не забывайте всегда сохранять резервные копии вашего кода и тестировать изменения на локальном сервере перед их внедрением на боевом сайте.