Произвольное меню в WP 3.0+ (wp_nav_menu)
Широко известно, что в WordPress 3.0 добавлена поддержка произвольных меню (настраиваемых меню). Вещь, на мой взгляд, крайне удобная и полезная. Собственно, отсюда и эта статья.
Удобство заключается в том, что теперь можно создавать и конфигурировать меню прямо из админки, добавляя ссылки кликами по чекбоксам и меняя порядок ссылок простым перетаскиванием. В меню можно добавить ссылки на страницы, категории и отдельные посты. Можно создавать многоуровневые меню, так же в меню можно добавлять свои произвольные ссылки, о которых WordPress не знает. В общем, полная свобода действий.
Однако, чтобы такая "свобода" была доступна, нужно, скажем так, легким движением мышки, настроить вывод произвольного меню в шаблон.
Использовать такие меню будет крайне удобно, если пользоваться мультисайтовой возможностью WordPress, потому что для разных сайтов можно будет настраивать разные меню, а шаблон для них использовать один.
Работает через таксономию nav_menu, а произвольные (внешние) ссылки, записываются в таблицу wp_posts. Такой подход более гибкий и динамичный, однако требует постоянной генерации таких меню.
Итак, приступим.
Видео по меню в WordPress
Включаем поддержку произвольных меню (wp_nav_menu)
Для начала нужно зарегистрировать возможность использования произвольных меню и слоты для будущих меню (местаположения куда могут быть размещены сами меню). Делается это с помощью функции register_nav_menu(), например в файле functions.php, так:
register_nav_menus( [ 'top' => 'Верхнее меню', // Название слота для меню в шаблоне 'bottom' => 'Нижнее меню' // Название другого слота меню в шаблоне ] );
Мы зарегистрировали 2 слота для меню с идентификаторами top и bottom с соответствующими им названиями. Идентификаторы нужны, чтобы использовать их в теме, в параметрах функции wp_nav_menu(), которая будет выводить созданное в админке меню. Названия зарегистрированных слотов мы увидим в админке, когда зайдем в раздел Внешний вид -> Меню.
После того, как слоты зарегистрированы, идем в админку и создаем свои меню (в данном примере 2 менюшки):
-
Задаем название меню. Меню в шаблоне можно выводить по указанному названию, функцией wp_nav_menu( [ 'menu'=>'Name' ] )
-
Добавляем элементы в меню. Используем левый блок: страницы ссылки, рубрики.
- Выбираем слот для меню (где будет расположено), так как мы зарегистрировали 2 слота, у нас будет 2 варианта: "Верхнее меню" и "Нижнее меню".
Поддержка меню в WP включается отдельно для темы, функцией add_theme_support('menus'). Однако, при регистрации слотов нет необходимости включать поддержку отдельно - это делается автоматически.
Вывод произвольных меню через функцию wp_nav_menu()
Важно: нюанс с отсутствующим меню
При использовании функции wp_nav_menu(), если указанный theme_location не существует или не назначено ни одно меню, WordPress автоматически переключается на wp_page_menu(), которая выводит список всех страниц. При этом параметры container, container_class и прочие начинают применяться к <ul>, а не к контейнеру, это может нарушить ожидаемую HTML-разметку.
Пример:
$menu = wp_nav_menu( [ 'theme_location' => 'my_location', 'container' => 'nav', 'container_class' => 'nav header__nav', 'menu_class' => 'header__list', 'menu_id' => 'my-id', 'echo' => false, ] ); echo htmlspecialchars( $menu );
Результат, когда нет "my_location" или в нем нет ни одного меню:
<nav id="my-id" class="header__list"> <ul> <li class="page_item page-item-14813"><a href="УРЛ">Заголовок страницы</a></li> </ul> </nav>
Результат, когда в "my_location" есть меню:
<nav class="nav header__nav"> <ul id="my-id" class="header__list"> <li id="menu-item-6411" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-6411"> <a href="УРЛ">Заголовок элемента меню</a> </li> </ul> </nav>
Подробнее читайте в комментарии.
Теперь, осталось вывести меню в шаблоне. Делается это функцией wp_nav_menu(), которая может принимать следующие параметры:
wp_nav_menu( array( 'menu' => '', // (string) Название выводимого меню (указывается в админке при создании меню, приоритетнее // чем указанное местоположение theme_location - если указано, то параметр theme_location игнорируется) 'container' => 'div', // (string) Контейнер меню. Обворачиватель ul. Указывается тег контейнера (по умолчанию в тег div) 'container_class' => '', // (string) class контейнера (div тега) 'container_id' => '', // (string) id контейнера (div тега) 'menu_class' => 'menu', // (string) class самого меню (ul тега) 'menu_id' => '', // (string) id самого меню (ul тега) 'echo' => true, // (boolean) Выводить на экран или возвращать для обработки 'fallback_cb' => 'wp_page_menu', // (string) Используемая (резервная) функция, если меню не существует (не удалось получить) 'before' => '', // (string) Текст перед <a> каждой ссылки 'after' => '', // (string) Текст после </a> каждой ссылки 'link_before' => '', // (string) Текст перед анкором (текстом) ссылки 'link_after' => '', // (string) Текст после анкора (текста) ссылки 'depth' => 0, // (integer) Глубина вложенности (0 - неограничена, 2 - двухуровневое меню) 'walker' => '', // (object) Класс собирающий меню. Default: new Walker_Nav_Menu 'theme_location' => '' // (string) Расположение меню в шаблоне. (указывается ключ которым было зарегистрировано меню в функции register_nav_menus) ) );
В данном примере в шаблон нужно вставить примерно (зависит от необходимых вам параметров) такие, 2 кода:
#1. Вывод меню по расположению
Верхнее меню. Вставляем в шапку шаблона (header.php), там где будет выводится верхнее (top) меню:
<?php wp_nav_menu( array( 'menu_class'=>'menu', 'theme_location'=>'top', 'after'=>' /' ) ); ?>
Выведет созданное в админке меню, прикрепленное к расположению "Верхнее меню" с подобной структурой:
<div class='<классы WP>'> <ul class='menu'> <li><a class='<классы WP>' href="#">Анкор ссылки</a> /</li> <li><a class='<классы WP>' href="#">Анкор ссылки</a> /</li> <li><a class='<классы WP>' href="#">Анкор ссылки</a> /</li> </ul> </div>
Нижнее меню. Вставляем в подвал шаблона (footer.php), там где будет выводится нижнее (bottom) меню:
<?php wp_nav_menu('menu_class=bmenu&theme_location=bottom'); ?>
Выведет созданное в админке меню, прикрепленное к расположению "Нижнее меню". Структура будет идентичная первой.
Обратите внимание, в первом варианте параметры были переданы через массив (array). Во втором через строку. Оба варианта правильны. Это обычное дело для функций WordPress - параметры можно передавать как массивом, так и строкой (строка потом преобразовывается в массив).
#2 Выводим меню по названию
Чтобы вывести меню по его названию можно воспользоваться аргументом 'menu'. Название указывается, то которое было задано при создании меню в админке. В нашем примере (см. картинку) "Главное меню". Аргумент menu обладает большим приоритетом чемtheme_location, а значит, если мы выводим по названию, то параметр theme_location будет игнорироваться.
<?php wp_nav_menu('menu=Главное меню'); ?>
Можно указать ID меню, а не название. Так, при изменении названия меню, код останется рабочим. ID меню можно посмотреть в УРЛ во время редактирования меню:
<?php wp_nav_menu('menu=455'); ?>
Заметки
Уберем обертку Div
Вы наверное обратили внимание, что меню "оборачивается", часто, ненужным тегом div. Его можно удалить, указав в аргументах для функции wp_nav_menu() пустой параметр 'container'=>''.
Изменяем параметры по умолчанию
Чтобы постоянно не указывать один и те же параметр для вставляемых меню, их можно переопределить в functions.php. Делается это через фильтр wp_nav_menu_args:
register_nav_menus( [
'top' => 'Верхнее меню',
'bottom' => 'Нижнее меню'
] );
add_filter( 'wp_nav_menu_args', 'my_wp_nav_menu_args' );
function my_wp_nav_menu_args( $args='' ){
$args['container'] = '';
return $args;
}
По аналогии, можно создать свои аргументы по умолчанию: $args['аргумент'] = 'значение'.
Проверка зарегистрировано ли меню
В WordPress так же есть, функция условия: has_nav_menu('top') - проверяет было ли зарегистрировано расположение меню top. Если меню не указано, то функция wp_nav_menu() сработает, как wp_list_pages(), но "обворачиватель" div останется, несмотря на то что в аргументах мы его убрали. Решить эту проблему можно так:
if( has_nav_menu('top') ){
wp_nav_menu( [
'container' => '',
'theme_location' => 'top',
'menu_class' => 'menu'
] );
}
else {
echo '<ul class="menu">';
wp_list_pages( array('depth' => 1, 'title_li' => '' ));
echo '</ul>';
}
Параметр walker
Из всех передаваемых аргументов, непонятным является walker. Для тех, кто хочет разобраться для чего он нужен, читайте раздел в описании функции wp_nav_menu(). Там коротко и ясно описан принцип. Если очень коротко, то с его помощью можно внедриться в процесс генерации меню и изменить его как угодно.
Включение доп. параметров у меню
Меню можно настроить, например, можно добавить возможность указывать CSS класс для элемента меню, для ссылки меню. Для этого откройте вкладку «Настройки экрана»:


