Как известно, функция WordPress wp_nav_menu() для вложенных меню использует просто вложенный в <li> тег <ul>.
Чаще всего это более чем достаточно, но иногда сложный дизайн меню требует больше элементов для вёрстки.
Что и было в моём случае. Я уже думал, что придётся выводить меню вручную, без использования wp_nav_menu(), однако, внимательнее перечитав документацию по ссылке выше, увидел очень красивое решение этой проблемы, специально заготовленное WordPress.
Итак, в своей предварительной html-вёрстке дизайна я сделал подменю, которое выглядело так:
<ul> <li class='has_sub'> <a href='#'>Item</a> <div class='sub'> <div class='sh'> </div> <div class='sb'> <ul> <li><a>Sum-menu_item</a> </ul> </div> </div> </li> </ul>
Каким образом заставить wp_nav_menu генерировать такую вёрстку? Оказывается, разработчики WordPress предусмотрели такую возможность. Существует класс Walker_Nav_Menu, который как раз предназначен для генерации тегов, обрамляющих различные пункты меню и подменю. В классе есть следующие функции:
start_lvl() | Вызывается перед тем, как начать вывод пунктов подменю |
end_lvl() | Вызывается после того, как все пункты меню выведены |
start_el() | Вызывается перед выводом очередного элемента меню |
end_el() | Вызываетяс после вывода очередного элемента меню |
Описание этого класса можно посмотреть в wp-includes/nav-menu-template.php. А у функции wp_nav_menu() есть такой параметр как walker, в который мы можем передать экземпляр своего класса, содержащий те же методы, который будет в этом случае использоваться вместо стандартного. Таким образом, для решения моей задачи мне потребовалось добавить простенький класс в файл functions.php своей темы:
class My_theme_menu_walker extends Walker_Nav_Menu {
function start_lvl(&$output, $depth = 0, $args = array()) {
$output .= "<div class='sub'><div class='sh'></div><div class='sb'><ul>";
}
function end_lvl( &$output, $depth = 0, $args = array()) {
$output .= "</ul></div></div>";
}
}
А сам вызов wp_nav_menu выглядит у меня в теме так:
wp_nav_menu(array("theme_location"=>"main_menu",
"container"=>false, // Контейнер мне не нужен
"menu_class"=>'', // класс для тега ul тоже без надомности
"walker"=>new My_theme_menu_walker() // Объект класса, который будет выводить обрамляющие теги
// Обязательно передать созданный объект, а не имя класса
));