Блог Михаила Крамера. PHP и JS
Альтернативная вёрстка подменю при использовании функции wp_nav_manu
09.01.2014

Как известно, функция 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() // Объект класса, который будет выводить обрамляющие теги
                                                           // Обязательно передать созданный объект, а не имя класса
                  ));
Комментарии