wp_nav_mеnu(), создание пользовательских меню

Использование меню такого типа очень удобно, особенно если делаешь сайт для заказчиков. Конечно, можно вывести рубрики при помощи wp_list_categories или вообще написать на HTML (лично я всегда так и делаю, когда создаю сайт для себя), но будет нудно, если пункты меню будут часто меняться и дополняться.

Для начала нужно включить поддержку меню темой, вставив этот код в файл functions.php:

if (function_exists('add_theme_support')) {
	add_theme_support('menus');
}

А это более правильный вариант с регистрацией областей темы:

if(function_exists('register_nav_menus')){
	register_nav_menus(
		array( // создаём любое количество областей
		  'main_menu' => 'Главное меню', // 'имя' => 'описание'
		  'foot_menu' => 'Меню в футере'
		)
	);
}

После этого в админке появится вкладка Внешний вид > Меню. Заходим туда и создаём своё меню, назовём его например «menu1».

Засуньте этот код в то место в теме, куда вы хотите вставить менюху:

<?php wp_nav_menu("menu=menu1"); ?>

Точно так же можно насоздавать ещё кучу менюшек, указывая в скобках их названия. Это был примитивный пример.

Итак, функция wp_nav_menu()

wp_nav_menu($args);

Параметры по умолчанию:

$args = array(
	'theme_location'  => , // область темы
	'menu'            => , // какое меню нужно вставить (по порядку: id, ярлык, имя)
	'container'       => 'div', // блок, в который нужно поместить меню, укажите false, чтобы не помещать в блок
	'container_class' => 'menu-{menu slug}-container', // css-класс блока
	'container_id'    => , // id блока
	'menu_class'      => 'menu', // css-класс меню
	'menu_id'         => , // id меню
	'echo'            => true, // вывести или записать в переменную
	'fallback_cb'     => 'wp_page_menu', // какую функцию использовать если меню не существует, укажите false, чтобы не использовать ничего
	'before'          => , // текст или html-код, который нужно вставить перед каждым <a>
	'after'           => , // после </a>
	'link_before'     => , // текст перед анкором ссылки
	'link_after'      => , // после анкора и перед </a>
	'items_wrap'      => '<ul id=\"%1$s\" class=\"%2$s\">%3$s</ul>', // HTML-шаблон
	'depth'           => 0 // количество уровней вложенности
);

Комментарии 37

  • DenPorsche16 ноября 2012 в 01:11 #

    Спасибо за Вашу работу! Помогли! Дай Бог Вам здоровья и успехов!

    • Миша16 ноября 2012 в 05:11 #

      Спасибо)

      • DenPorsche20 ноября 2012 в 21:11 #

        Все вроде получилось, но есть одно НО)
        (установил плагин UberMenu). Хочу добавить это меню в сайдбар.

        Сделал все как у вас.

        Когда выбираю области темы, которые уже были в самой теме, то плагин работает.

        А в созданной мной - нет. Не подскажете, что может быть?

      • Миша21 ноября 2012 в 06:11 #

        посмотри, может зависит от css класса меню

  • DenPorsche21 ноября 2012 в 11:11 #

    Спасибо! Посмотрю!

  • Nurlan10 июня 2013 в 09:06 #

    А как стилизовать, чтобы меню стояло в один ряд? Без этого меню появляется, как рубрики в сайт-баре.

    • Миша10 июня 2013 в 10:06 #

      Добрый день,
      можно использовать следующие CSS-стили к соответствующим элементам меню:

      ul{
      	list-style: none;
      }
      li{
      	display:inline-block;
      }

      или

      ul{
      	list-style: none;
      	overflow:hidden;
      }
      li{
      	display:block;
      	float:left;
      }
  • VRS21 октября 2013 в 04:10 #

    Доброй ночи, Михаил.
    Надеюсь на Вашу помощь, сама зашла в тупик.
    Пытаюсь написать walker, который группирует пункты меню по 2

     
    <ul class="table">
     
       <li>
         <ul class="row">
           <li> Ли №1</li>
           <li> Ли №2</li>
         </ul>
       </li>
     
       <li>
         <ul class="row">
          <li> Ли №3 </li>
          <li> Ли №4</li>
         </ul>
       </li>

    Чтобы визуально разделить на две колонки.
    Попробовала так

     function start_el( &$output, $item, $depth, $args ) {  
        global $wp_query;  
     
    ####
    тут всякие атрибуты
    ####
    
     
    	$i= $item->ID;
    	if ($i%2 != 0):
    		$cat_right = '<li><ul class="row">'; 
    	endif; 
     
     
     
       $output .= $cat_right .  '<li id="item-'. $item->ID . '">';  
     
        $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );  
     
    }  
     
    function end_el(&$output, $item, $depth, $args)
    	{
     
     
    	$i= $item->ID;	
    	if ($i%2 == 0):
    		$cat_left = '</ul></li>'; 
    	endif; 
     
     
    		$output .= "</li>". $cat_left ;
    	}

    И вроде нормально, но если я поменяю местами пункты в уже созданном меню, то всё съезжает..
    Пробовала прикрутить обработчик из кодекса, но у меня он упорно ставить even ВСЕМ элементам li верхнего уровня. А odd только если depth меняю - создаю подменю, вот у него odd-класс.

    Подскажите, как сделать чет-нечет?

  • VRS28 января 2014 в 08:01 #

    Миш, а можно еще немного помощи попросить =)?

    Сейчас у меня такая таксономия

    произвольная ссылка (href="#")>> рубрика >> ее подрубрика >> запись

    И когда я на странице записи — произвольной ссылке НЕ присваивается класс current .

    Прочла, что произ.ссылки хранятся в БД отдельно...
    По логике тогда в валкере нужно сделать проверку, чтобы на странице записи присваивать current класс самому высшему родительскому пункту меню, если такой класс есть у дочернего.
    Но что-то уже весь рунет и буржунет облазила, а решения не нашла.

  • Nurlan28 января 2014 в 18:01 #

    Уважаемый, хоть я и оставлял комментарий здесь, но не помню, чтобы подписывался на новые комментарии к данной статье. Возможно, я просто не заметил галочку, которая стоит по умолчанию. Прошу Вас отписать от получения уведомлений о новых комментариях. Если уж сделали фичу на подписку, резонно было бы дать людям самостоятельно отписаться.

  • VRS12 марта 2014 в 16:03 #

    Добрый день, Миша.
    Не подскажешь как добавить номер в классы пунктов верхнего уровня меню?
    Чтобы было так

    <ul>
    <li class="li-1"></li>
    <li class="li-2"></li>
    <li class="li-3"></li>
    <ul>
    <li></li> 
    <li></li>
    </ul>
    <li class="li-4"></li>
    <li class="li-5"></li>
    </ul>

    menu_order нумерует по порядку без привязки к depth

    • Миша13 марта 2014 в 08:03 #

      Добрый день!
      я бы залез в файл, где определяется функция и поискал бы там фильтры для классов, ну и скорее всего через волкер можно реализовать.

  • VRS13 марта 2014 в 11:03 #

    Через волкер и пытаюсь =)..
    но стандартно $i=0 if (depth=0) $i++ не получается прикрутить.

    • Миша16 марта 2014 в 12:03 #

      а почему?

    • Миша22 июля 2014 в 09:07 #

      Думаю тут в волкере поможет параметр $item->menu_item_parent. То есть, если этот параметр не существует, то делаем инкремент счетчика.

      P.S. Скажу честно, когда ты меня три месяца назад спросила про это, я в волкерах был полным нубом :)

      • VRS22 июля 2014 в 13:07 #

        Да я сама методом тыка всё осваиваю =)..
        Я уже там что-то другое навертела, но на будущее запомню), спасибо!

  • VRS16 марта 2014 в 15:03 #

    Если я в start_el дописываю в скобки $i=0, потом пишу $i++ и условие, то соответственно li каждый раз обнуляется и у всех class="li-1". А если не писать эту переменную или не присваивать ей нулевое значение, то счетчик вообще не работает.
    Или я что-то напутала?

  • adward26 марта 2014 в 02:03 #

    Михаил, доброго времени суток. У меня такая трабла:
    Клиент требует убирать из меню те страницы сайта (меню основано на страницах), для которых стоит статус "Черновик" или "На утверждении".

    Можно ли каким нибудь способом, либо:
    a) не формировать это меню в момент сборки, или же
    б) присваивать такому пункту какой либо, скажем, класс, например class="hiddenitem"

    В данный момент меню формируется следующим образом:

    $args = array(
    	'theme_location'=>'equipment-menu',
    	'container'=>'div',
    	'container_class'=>'children_menu_top',
    	'container_id'=>'menu',
    	'menu_class'=>'sf-menu',
    	'menu_id'=>'children_menu',
    	'before'=>'<span>',
    	'after'=>'</span><div class="validm"></div>',
    	'fallback_cb'=>false
    );
    wp_nav_menu($args);

    Спасибо!

    • VRS26 марта 2014 в 12:03 #

      Я не Миша =), но может Вам подключить валкер и в нем прописать что-то вроде

      function start_el( &$output, $item, $depth, $args ) {  
          global $wp_query;         
       
      $id = $item->object_id;
       if ( get_post_status ( $id ) != 'draft' ) {
      		//  тут построение элемента $item_output и  вывод $output 
      	}
  • Almaz5 декабря 2014 в 13:12 #

    Здравствуйте!
    Создал 2х уровневое меню в админке.
    Пытаюсь создать новую тему.
    Вывожу меню так:

    <?php wp_nav_menu( array( 'theme_location' => 'primary', 'menu_class' => 'nav-menu' ) ); ?>

    Почему то вместо такого результата:

    <ul>
    	<li><a href=""></a></li>
    	<li>
    		<a href=""></a>	
    		<ul>
    			<li><a href=""></a></li>
    			<li><a href=""></a></li>
    			<li><a href=""></a></li>
    			<li><a href=""></a></li>
    		</ul>
    	</li>
    	<li>
    		<a href=""></a>
    		<ul>
    			<li><a href=""></a></li>
    			<li><a href=""></a></li>
    			<li><a href=""></a></li>
    			<li><a href=""></a></li>
    		</ul>	
    	</li>
    	<li><a href=""></a></li>
    </ul>

    Получаю такой:

    <ul>
    	<li><a href=""></a></li>
    	<li><a href=""></a></li>
    	<li><a href=""></a></li>
    	<li><a href=""></a></li>
    	<li><a href=""></a></li>
    	<li><a href=""></a></li>
    	<li><a href=""></a></li>
    	<li><a href=""></a></li>
    </ul>

    Почему не получаю ожидаемого результата? Есть какие-то тонкости использования функции wp_nav_menu?

    • Миша6 декабря 2014 в 07:12 #

      Здравствуйте! Попробуйте:

      wp_nav_menu( array( 'theme_location' => 'primary', 'menu_class' => 'nav-menu', 'depth' => 2  ) );
  • Александр6 февраля 2015 в 15:02 #

    Как через get_the_post_thumbnail() прикрепить миниатюры в навигационное меню. не могу сообразить.

  • Роман15 марта 2015 в 00:03 #

    а можно ли внутрь тега <a> запихнуть тег с атрибутом title?

  • Alex Spain30 июля 2015 в 13:07 #

    Как прописать атрибут title к ссылкам в меню Рубрики на сайте http://espana-live.com/? В каком файле внести изменения? nav-menu.php или nav-menu-template.php?

  • Александр4 сентября 2015 в 00:09 #

    Михаил, добрый день! Помню как-то вы мне помогли в одном вопросе, за это спасибо! Может поможете и в этом?

    Суть в следующем: есть плагин WP-Recall, там есть личный кабинет в котором выводятся кнопки, делаю тему для WordPress и хотел бы сделать меню, что бы эти кнопки отображались в меню темы. а не на странице плагина!

    Разработчик написал, что это возможно, написал следующее:

    "Добрый день, да, это вполне возможно, все действующие вкладки личного кабинета можно получить в глобальной переменной $rcl_option['tabs'], затем обратиться к массиву данных нужного меню сайта и добавить туда нужные пункты используя данные из $rcl_option['tabs'], в результате меню выведет добавленные кнопки.

    Чтобы получить объекты нужного меню вроде можно использовать фильтр wp_nav_menu_objects, там два аргумента $sorted_menu_items и $args, в первом находятся сформированные объекты пунктов меню, а во втором настройки переданные через функцию wp nav menu."

    Вот подскажите, как получить глобальную переменную $rcl_option['tabs'], я не пойму...

  • Миша4 сентября 2015 в 07:09 #

    Добрый день!
    Возможно я мог бы подсазать вам точнее, если бы сам пользовался плагином WP-Recall, а вообще к глобальной переменной обратиться легко:

    global $rcl_option;
    $tabs = $rcl_option['tabs'];
    • Александр4 сентября 2015 в 15:09 #

      И что мне потом делать с $tabs ?

      • Миша5 сентября 2015 в 07:09 #

        Вопрос был, как получить глобальную переменную $rcl_option['tabs'] и я ответил.

        Я так полагаю, после этого у вас имеется массив элементов — тут уже можете делать что угодно, либо просто дописать в файлах темы, либо, как вам ответил супорт, использовать фильтр wp_nav_menu_objects, либо функцию из меню. На самом деле ничего сложного, главное понимать в общих чертах, как работают массивы PHP.

  • Алексей6 декабря 2015 в 14:12 #

    На странице меню выводится так

    <?php $walker = new Menu_Description; ?>
    <?php wp_nav_menu( array('menu' => 'Навигация по сайту','container' => 'nav','container_class' => 'menu','items_wrap' => '<a href="#" id="pull">меню</a><ul>%3$s</ul>','walker' => $walker ) ); ?>

    Подскажите пожалуйста как можно туда вставить микроразметку

    itemscope itemprop="http://schema.org/SiteNavigationElement"

Оставить комментарий / вопрос

phpjsHTMLCSSSQLПросто код
  Для того, чтобы оставить комментарий, пожалуйста, зарегистрируйтесь или авторизуйтесь на сайте.
  • Миша: Привет ещё раз, не поверишь, реально не сталкивался с этим вопросом. По теории можно сказать следующее: во-первых,...

  • Миша: Привет, вообще без проблем, делаешь всё через require(), require_once() - выбирай любую, какая больше нравится.

  • Виталий Моргунов: Привет! Не могу разобаться, как я могу контролировать порядок подключения стилей. В моем случае мне нужно чтобы стили...

  • Миша: Спасибо!

  • w0rmak: Это было просто. Нашел код в интернете. Добавьте и себе ymaps.load(function () { var input = document.getElem...