Меню в WordPress. Волкер меню.

Не хотите читать этот длинный текст? Могу предложить мой видеоурок про меню!

Функционал меню появился в версии WordPress 3.0. До этого вывод навигации обычно осуществлялся при помощи функций wp_list_categories() и wp_list_pages(). Конечно, иногда бывает нужно вывести категории сайта в виде меню и ещё чтобы дочерние категории были в виде выпадающих списков, но гораздо удобнее, если каждый элемент меню можно добавить, изменить или удалить по отдельности в админке сайта.

Также в меню WordPress вы можете изменять порядок элементов банальным перетаскиванием.

Давайте подробно рассмотрим весь процесс добавления меню. Для начала переходим в админке во Внешний вид > Меню… У вас нет такого пункта? Окей, значит вашей темой меню не поддерживаются, сейчас мы это исправим, рассмотрим даже два способа.

Способ 1. Включение поддержки меню в теме WordPress

Для активации функционала меню вы можете использовать функцию add_theme_support(). Всё просто и легко, вставляем этот код в functions.php текущей темы и да, после этого мы можем зайти в админку и начать создавать меню.

add_theme_support('menus');
Функционал меню в WordPress

От себя добавлю, что этот способ я не люблю и практически его не использую. На мой взгляд он несколько ограничивает наши возможности и хорош только тогда, когда вы хотите использовать меню в виджетах (т.е. только в виджетах).

Способ 2. Регистрация областей темы

В двух словах, область темы — это такая условная область, которая предназначена для вывода меню. Условная, потому что сама по себе она нигде не выводится. Как всё это происходит по порядку:

  1. Сначала мы регистрируем область темы. После этого у нас сразу появляется функционал меню тут: Внешний вид > Меню. Допустим мы создадим две области темы: «Шапка сайта» и «Левый сайдбар».
  2. Затем, при создании меню мы указываем область темы, в которой хотим отображать данное меню. Также можно указать несколько областей сразу.
  3. И завершающий шаг. В разных частях темы выводим меню, соответствующие разным областям.

Не знаю, насколько понятно я всё это объяснил в теории, но на практике определенно будет легко. Итак, для того, чтобы зарегистрировать область темы, нам понадобится функция register_nav_menus(). Давайте тогда создадим две области, о которых я писал выше: «Шапка сайта» и «Левый сайдбар».

Да, код — в functions.php.

register_nav_menus(
	array(
		'head_menu' => 'Шапка сайта',
		'side_menu' => 'Левый сайдбар'
	)
);

Создание меню

Давайте теперь разберемся, как создавать и как управлять меню. В принципе в админке WordPress всё сделано интуитивно, но на всякий случай мы всё подробно рассмотрим.

Переходим во Внешний вид > Меню, указываем в поле название нового меню и нажимаем кнопку Создать меню.

Создаем новое меню в админке сайта

В итоге у нас получилось вот что:

Страница редактирования меню в WordPress.

Теперь, используя колонку со списком страниц и рубрик, давайте заполним меню.

  • Для того, чтобы добавить один или несколько элементов в меню, просто отметьте их галочкой и нажмите кнопку Добавить в меню.
  • Если вы не видите нужной вам страницы в списке, перейдите на вкладку «Все» либо воспользуйтесь вкладкой «Поиск».
  • Для того, чтобы добавить в меню ссылку на главную страницу, в списке страниц перейдите на вкладку «Все», отметьте галочкой элемент «Главная» и добавьте его в меню.
  • По умолчанию в меню можно добавлять только страницы, рубрики и произвольные ссылки. Если вам нужно добавить в меню произвольный тип поста, элементы созданной вами таксономии или записи, перейдите по этой ссылке.
  • Вы можете изменять порядок элементов перетаскиванием.
  • Также, чуть перетащив элемент вправо, его можно сделать дочерним для вышестоящего элемента. Дочерние элементы можно будет реализовать в виде выпадающего списка на сайте.
  • Если отметить галочкой «Автоматически добавлять в это меню новые страницы верхнего уровня», то, после публикации новох страниц, они автоматически будут добавляться в конец этого меню (тогда такое меню лучше будет добавлять в сайдбар, так как в шапке может просто не хватить места).
  • Отметьте галочкой области темы, в которой вы хотите отобразить это меню.

Всё получилось? Тогда нажимаем кнопку Сохранить меню.

Меню WordPress.

Вы можете удалить или отредактировать (переместить, переименовать) элемент, нажав на стрелку справа (на скриншоте отмечена красным).

Редактировать элемент меню.

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

Управление областями темы.

CSS-классы для отдельных элементов меню, открытие некоторых ссылок в новой вкладке

Как?

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

Видите в правой верхней части экрана вкладки «Настройки экрана» и «Помощь»? Нам нужна первая. Кликаем по ней, после чего у нас выпадает блок, в котором можно включить дополнителные настройки элементов меню.

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

Дополнительные настройки элементов меню.

Как добавлять в меню записи, таксономии и произвольные типы постов

На предыдущых скриншотах видно, что по умолчанию в меню можно добавлять только страницы, ссылки и рубрики. А если нам надо добавить запись? Конечно, вы можете добавить её через «ссылки», но тогда, если изменится URL записи, у нас появится ошибка 404.

Решение этой задачи есть и оно очень простое.

Записи и метки

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

Добавляем записи и метки в меню WordPress.

Таксономии и типы постов

И у тех и у других принцип один и тот же — при регистрации таксономии (register_taxonomy()) или типа поста (register_post_type()) значение параметра функции show_in_nav_menus должно быть true.

register_taxonomy('mytaxonomy',
		array('post'),
		array(
			...
			'show_in_nav_menus' => true,
			...
		)
);
$args = array(
	...
	'show_in_nav_menus' => true,
	...
);
register_post_type('product',$args);

Если после этого элементы таксономии или типы записей так и не появились в меню, в правом верхнем углу страницы откройте вкладку «Настройки экрана» и включите их там.

Вывод меню на сайте

Сейчас мы рассмотрим два примера того, как можно вывести меню на сайте, в каждом из них будет использоваться одна и та же функция для вывода wp_nav_menu().

Пример 1. Используем для вывода ID / ярлык / название меню

Если вы всё-таки захотите использовать этот первый способ, я рекомендую в качестве параметра задавать только ID меню. Читайте подробнее о том, как узнать ID меню или его ярлык.

В итоге имеем:

$args = array(
	'menu'	=> 381
);
wp_nav_menu( $args );

Пример 2. Использование зарегистрированных областей темы для вывода меню

На первый взгляд, этот пример может показаться сложнее, потому что сначала нам требуется зарегистрировать область темы (в этом посту мы уже зарегали две области — head_menu (Шапка сайта) и side_menu (Левый сайдбар), затем, при создании меню, нам надо присвоить его одной из этих областей (мы уже создали с вами меню и присвоили его области head_menu) и только после этого мы можем выводить область с содержащимся в ней меню на сайте.

Но на самом деле этот способ намного лучше, ведь для того, чтобы присвоить меню, скажем, для шапки, или отключить меню, или поменять меню местами, вам не придется каждый раз залазить в код темы WordPress.

А если вы разработчик тем WordPress, то первый способ, который просто выводит определенное меню из базы данных, для вас и вовсе не подойдет.

$args = array(
	'theme_location' => 'head_menu'
);
wp_nav_menu( $args );

Функция wp_nav_menu() имеет большое количество параметров, все они описаны в документации этой функции.

Вставляем меню в сайдбар (в виде виджета)

Существует ещё и третий способ вывода меню на сайте — в виде виджета. Для этого переходим во Внешний вид > Виджеты, находим виджет «Произвольное меню» и перетаскиваем его в сайдбар. Если по каким-то причинам у вас не получается это сделать, сначала прочитайте пост про сайдбары в WordPress.

Виджет меню в WordPress

Переделываем меню при помощи волкера

Рассмотрение класса Walker безусловно заслуживает отдельного поста. Сейчас я покажу лишь простой пример, который позволит вам использовать этот класс при выводе меню, тем самым подстраивая его под свой сайт, меняя HTML-разметку, добавляя различные атрибуты элементам и PHP-условия.

Для начала нужно создать класс, у меня это True_Walker_Nav_Menu, код которого я вставил в functions.php текущей темы.

Хочу сказать, что в этом примере класс не будет делать никаких изменений, он выведет элементы меню в их первоначальном виде. Зато вы сможете использовать этот класс как шаблон, если вам понадобится сделать какие-то изменения в структуре меню.

class True_Walker_Nav_Menu extends Walker_Nav_Menu {
	/*
	 * Позволяет перезаписать <ul class="sub-menu">
	 */
	function start_lvl(&$output, $depth) {
	// для WordPress 5.3+
	// function start_lvl( &$output, $depth = 0, $args = NULL ) {
		/*
		 * $depth – уровень вложенности, например 2,3 и т д
		 */ 
		$output .= '<ul class="menu_sublist">';
	}
	/**
	 * @see Walker::start_el()
	 * @since 3.0.0
	 *
	 * @param string $output
	 * @param object $item Объект элемента меню, подробнее ниже.
	 * @param int $depth Уровень вложенности элемента меню.
	 * @param object $args Параметры функции wp_nav_menu
	 */
	function start_el( &$output, $item, $depth, $args ) {
	// для WordPress 5.3+
	// function start_el( &$output, $item, $depth = 0, $args = NULL, $id = 0 ) {
		global $wp_query;           
		/*
		 * Некоторые из параметров объекта $item
		 * ID - ID самого элемента меню, а не объекта на который он ссылается
		 * menu_item_parent - ID родительского элемента меню
		 * classes - массив классов элемента меню
		 * post_date - дата добавления
		 * post_modified - дата последнего изменения
		 * post_author - ID пользователя, добавившего этот элемент меню
		 * title - заголовок элемента меню
		 * url - ссылка
		 * attr_title - HTML-атрибут title ссылки
		 * xfn - атрибут rel
		 * target - атрибут target
		 * current - равен 1, если является текущим элементом
		 * current_item_ancestor - равен 1, если текущим (открытым на сайте) является вложенный элемент данного
		 * current_item_parent - равен 1, если текущим (открытым на сайте) является родительский элемент данного
		 * menu_order - порядок в меню
		 * object_id - ID объекта меню
		 * type - тип объекта меню (таксономия, пост, произвольно)
		 * object - какая это таксономия / какой тип поста (page /category / post_tag и т д)
		 * type_label - название данного типа с локализацией (Рубрика, Страница)
		 * post_parent - ID родительского поста / категории
		 * post_title - заголовок, который был у поста, когда он был добавлен в меню
		 * post_name - ярлык, который был у поста при его добавлении в меню
		 */
		$indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
 
		/*
		 * Генерируем строку с CSS-классами элемента меню
		 */
		$class_names = $value = '';
		$classes = empty( $item->classes ) ? array() : (array) $item->classes;
		$classes[] = 'menu-item-' . $item->ID;
 
		// функция join превращает массив в строку
		$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
		$class_names = ' class="' . esc_attr( $class_names ) . '"';
 
		/*
		 * Генерируем ID элемента
		 */
		$id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
		$id = strlen( $id ) ? ' id="' . esc_attr( $id ) . '"' : '';
 
		/*
		 * Генерируем элемент меню
		 */
		$output .= $indent . '<li' . $id . $value . $class_names .'>';
 
		// атрибуты элемента, title="", rel="", target="" и href=""
		$attributes  = ! empty( $item->attr_title ) ? ' title="'  . esc_attr( $item->attr_title ) .'"' : '';
		$attributes .= ! empty( $item->target )     ? ' target="' . esc_attr( $item->target     ) .'"' : '';
		$attributes .= ! empty( $item->xfn )        ? ' rel="'    . esc_attr( $item->xfn        ) .'"' : '';
		$attributes .= ! empty( $item->url )        ? ' href="'   . esc_attr( $item->url        ) .'"' : '';
 
		// ссылка и околоссылочный текст
		$item_output = $args->before;
		$item_output .= '<a'. $attributes .'>';
		$item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
		$item_output .= '</a>';
		$item_output .= $args->after;
 
 		$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
	}
}

Если вам нужны ещё параметры объектов $item, смотрите документацию функции wp_get_nav_menu_items(), которая кстати является ещё одним нестандартным способом вывода меню в WordPress.

Окей, класс вставили, второй шаг — добавить параметр walker в функцию wp_nav_menu(). То есть, если у вас уже используется меню на сайте, не нужно менять его код на тот, который указан тут ниже, надо всего лишь добавить туда ещё один параметр.

$args = array(
	'theme_location' => 'head_menu',
	'walker'=> new True_Walker_Nav_Menu() // этот параметр нужно добавить
 
);
wp_nav_menu( $args );

Вот и всё, теперь, редактируя класс, вы сможете отредактировать и ваше меню. Всё просто. Если не получается, то смотрите про волкеры во второй половине этого видео.

Миша

В последние годы я долго не знал, что мне делать с сайтом misha.blog, ведь он практически не приносит никакого профита, но недавно я осознал, что моя миссия – способствовать распространению WordPress. Ведь WordPress – это лучший движок для разработки сайтов – как для тех, кто готов использовать заложенную структуру этой CMS, так и для тех, кто предпочитает headless решения.

Сам же я впервые познакомился с WordPress в 2009 году. Организатор WordCamp. Преподаватель в школах Epic Skills и LoftSchool.

Если вам нужна помощь с вашим сайтом или может даже разработка с нуля на WordPress / WooCommerce — пишите. Я и моя команда сделаем вам всё на лучшем уровне.

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

  • Роман 22 октября 2014 #

    Хороший урок. Жаль я уже сделал менюшку на WP 4.1 theme Twenty Fifteen. Мне пригодилось бы. А так пришлось фактически интуитивно, используя код самой темы переделывать, в сети не так уж и много уроков нормального качества на данную тематику, искать было в лом (копошиться в гуано, если честно).
    Вы бы поковырялись в Twenty Fifteen, уроков про неё сделали бы. Тема просто обалденная, хотя и отличается под капотом. Могу даже список первоочередных вопросов написать /те, которые возникают почти сразу после активации темы/.

    • Миша 23 октября 2014 #

      Напиши, я и читатели моего блога будут благодарны )

      • Роман 25 октября 2014 #

        Да, я считаю, что пора сделать статью про "Twenty Fifteen". Эта дефолтная тема по своему уникальна и её необычность не только в концепции дизайна. Дело в том, что внимательному глазу открывается простая истина - она вообще не заточена под банерную рекламу.
        Глядя на неё, сама мысль поставить баннер или сделать длинное меню с прокруткой (через виджеты, к примеру) кажется кощунственной. В ней явственно чувствуется "мобильные" корни, т.е. создали её для мобильных гаджетов, а после приспособили для настольных наших, родных...
        И это сказывается на очень даже на многом. Я поковырялся тут под капотом и могу заявить, что настроить прокрутку сайдбара не проблема, как и сделать уже его, но... Но тогда вы можете просто скачать тему "Fukasawa" и через CSS закрепить её сайтбар - то же самое.
        Нет, очарование и изюминка (есть они в ней, есть) заключаются именно в тех пропорциях, что в ней от рождения.
        Что может заинтересовать юнного кастомайзера?
        Наверное, следующее:
        совместимость с популярными плагинами (многие прошлогодние конфликтуют, а уж двух-трех летние...особенно если их несколько, вообще убивают), как убрать дату(полностью), автора (полностью), как отрегулировать ширину сайтбара, способ уменьшения длинны белых линий, разделяющих меню, как убрать полосу прокрутки на сайтбаре, как заменить социальное меню на подобное верхнему (с его свойствами), как сочетать цвета в теме (там дается три цветового поля и их нужно подобрать, дабы не отпугивали посетителей).
        Вышеперечисленный список - это те вопросы, что у меня возникли в перые полчаса общения с 2015. И вот уже несколько дней я её тестирую. Совершенно честным образом я пытаюсь уйти от неё, бросить сие чудовище, но... вот уже полтора десятка тем проиграли соревнование (готовлю к запуску пару сайтов). Я все время возвращаюсь к ней, ведь разработчик этого чудовища следовал столь почитаемому мной девизу: Совершенство - это когда нечего отнять.
        Я отнял, не было там совершенства. Убрал футер (визуально полностью), заменил виджет на второе меню (статьи выводяться через пункты меню), убрал прокрутку (сайтбар полностью зафиксированн).
        ...и... теперь смотрю на это совершенство и понимаю, какой чудовищный заговор готовят крупнейшие игроки интернета (типа Гугола и иже с ним). Слишком глубоко проработанна и измененна парадигма сайтостроения при разработке этой темы. Не верю я в то, что разработчики ВП "просто решили", слишком коренные изменения проглядывают за этим.
        И все это оч. неплохо укладывается в то, что мы видим в политике развития Гугла или того же Яндекса. Грядут перемены. Большие. Как люди, по полёту ласточки предсказывают дождь, так и выход этой темы (как подтверждение появления такого подхода, вспомним Виндовс с его Метро и плоским дизайном), сигнализирует о Новой Волне.
        Станем ли мы новыми серферами или будем поглощенны изменениями - зависит от нас. А я призываю: "Все на покорение 2015"!

  • Григорий 14 ноября 2014 #

    А где закрывается тег li?
    Дизайн таков, что нужно html код меню усложнить, но закрывающиеся li-шки остаются

    • Миша 14 ноября 2014 #

      Этот тег вшит. Возможно для ваших целей больше подойдёт функция wp_get_nav_menu_items().

  • Григорий 14 ноября 2014 #

    Спасибо за ответ
    Не особо удобно, когда что-то где-то вшито и находится в кукуево)
    Пришлось nav-menu-template дорабатывать

  • Толя 15 декабря 2014 #

    на моем сайте http://sweethomeua.com/ на главной странице при выборе в меню: открытки-события, меню пропадает под слайдером, как сделать поверх слайдера? Тема Twenty Twelve

    • Миша 16 декабря 2014 #

      увеличить в css значение z-index.

      • Толя 16 декабря 2014 #

        спасибо!!!!!!!!!!!!! все супер

  • VRS 4 марта 2015 #

    А можно как-то прикрепить walker к тем меню, которые выводятся через виджеты?

    • VRS 4 марта 2015 #

      Конечно, отвечу я сама себе)) - http://wpsmith.net/2011/tutorials/how-to-add-menu-descriptions-featured-images-to-wordpress-menu-items/ - если кому-то еще будет необходимо

      • Миша 5 марта 2015 #

        Спасибо 🙂 Не всегда успеваю тебе отвечать, проверяю комменты раз в день)

  • Алексей 8 апреля 2015 #

    Здравствуйте Михаил! Подскажите пожалуйста при использование Walker в вашем примере кода как можно удалить полностью class=" " у элемента li Если удаляю строчку

    $class_names = ' class="' . esc_attr( $class_names ) . '"';

    то class=" " у элемента li удаляется. Но тогда активный пункт меню выглядит так

    <licurrent-menu-item></licurrent-menu-item>

    при этом пропадает выделение пункта меню

    • Миша 8 апреля 2015 #

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

      /*
       * Генерируем элемент меню
       */
      $output .= $indent . '<li' . $id . $value . $class_names .'>';

      Станет:

      $output .= $indent . '<li' . $id . $value .'>';
  • Алексей 8 апреля 2015 #

    class=" " у элемента li удалился но теперь не выделяется активный пункт меню это можно как нибудь поправить?

    • Алексей 9 апреля 2015 #

      А не подскажите есть ли другой способ вывести описание в пункты меню не используя Walker?

  • Dennis 9 апреля 2015 #

    Присоединяюсь к вопросу. Как избавиться от всех классов, кроме активного пункта меню???

    • Алексей 9 апреля 2015 #

      если вас не интересует Walker то избавиться от всех классов, кроме активного пункта меню можно

      add_filter('nav_menu_css_class', 'ydalit_atribyti_y_li', 100, 1);
      add_filter('nav_menu_item_id', 'ydalit_atribyti_y_li', 100, 1);
      add_filter('page_css_class', 'ydalit_atribyti_y_li', 100, 1);
      function ydalit_atribyti_y_li($peremennnya) {if (is_array($peremennnya)) : return array_intersect($peremennnya, array('current-menu-item')); else : return ''; endif;}
      • Dennis 10 апреля 2015 #

        Интересует именно walker. Но без лишних классов. Требуется только активный пункт меню. У вас такой же результат по коду выше?

        • Миша 10 апреля 2015 #
          $class_names = ( $item->current == 1 ) ? ' class="current-menu-item"' : '';
          $output .= $indent . '<li' . $id . $value . $class_names .'>';

          Вот теперь правильно, забыл про атрибут class.

          • Алексей 10 апреля 2015 #

            Спасибо огромное!

          • Дмитрий 6 августа 2015 #

            Не работает если уровень вложенности более одного.
            Например, если речь идет о /wordpress/nav-menu-walkers.html записи, которая лежит в рубрике.

            + не будет работать если /blog/wordpress/nav-menu-walkers.html - то есть в рубрике Блог дочерняя рубрика wordpress.

            Как решить задачу?(((

            • Миша 7 августа 2015 #

              А что именно не работает?

              • Дмитрий 7 августа 2015 #

                current не принимает значение 1.
                current_item_ancestor и current_item_parent видимо надо тоже добавлять в проверку. не могу понять как.

                Подскажете?(((

                • Миша 8 августа 2015 #

                  Боюсь, что это нужно смотреть и тестировать весь код, с ходу ничего не могу сказать.

                  • Дмитрий 12 августа 2015 #

                    Можно надеяться на помощь в решении вопроса?

                    Сам никак не осилю...

                    • Миша 13 августа 2015 #

                      Пришлите мне тему по email или вк.

          • Алексей 7 января 2016 #

            Михаил Подскажите пожалуйста что еще нужно добавить чтобы в активном пункте меню не было ссылки на страницу где находишься!!?

            • Миша 9 января 2016 #

              В самом конце кода волкера используйте проверку:

              if( $item->current == 1 ) {
               
              }
              • Алексей 9 января 2016 #

                я не силен в php Что именно нужно написать в скобках? Пожалуйста!?

                • Миша 10 января 2016 #

                  Смотрите, в статье есть вот такой участок кода:

                  $item_output .= '<a'. $attributes .'>';
                  $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
                  $item_output .= '</a>';

                  То есть получается, если элемент текущий, то вам не нужна 1 и 3 строка.

                  • Алексей 10 января 2016 #

                    Спасибо! в этих 3-х строчках тег "а" заменил на span и удалил из первой строки $attributes Теперь в пункте меню нет ссылки когда там находишься а название пункта в тегах span Так будет правильно? или span на div заменить?

                    • Миша 10 января 2016 #

                      Тут лучше span я думаю.

  • VRS 17 апреля 2015 #

    Привет, Миш.
    Ты не подскажешь, может видел плагин или код, чтобы сделать как тут https://core.trac.wordpress.org/ticket/14134#comment:17 . Чтобы можно было сохранять отдельно каждый пункт меню, а не всё целиком.

    • Миша 18 апреля 2015 #

      Привет!
      Увы не знаю. Но идея очень интересная, уже хочу написать об этом 🙂

      • VRS 18 апреля 2015 #

        Будет интересно почитать). Я гуглила всю ночь, но такого не нашла.
        Единственно, сейчас сижу размышляю, что если записывать только один пункт, то следующий после него будет иметь тот же порядковый номер расположения в меню..
        В общем буду очень ждать твоих новых статей.
        Пользуясь случаем - Спасибо. Очень часто меня твой блог выручает).

  • Владимир 29 апреля 2015 #

    Тема отличная.
    Вопрос по этой теме ВАЛКЕРа:
    Можно ли при помощи этой функции вывести количество записей как выводит их стандартное меню категорий.
    Если да то как это сделать опиши пожалуйста?

    • Миша 29 апреля 2015 #

      А что подразумевается под "стандартным меню категорий" ?

  • Владимир 29 апреля 2015 #

    Вот картинка http://i.stack.imgur.com/IfCjq.jpg.

  • Владимир 29 апреля 2015 #

    можно ли сделать так как на картинке с помощью WALKER'a если ДА то как это написать?

    • VRS 29 апреля 2015 #

      Попробуйте так

      В function start_el

      global $wp_query;  
      $count_category = '';
      if($item->object == 'category')  { 
      $cat_id = $item->object_id;
      $count_category = get_category($cat_id)->category_count;
      }
      // И дальше в районе
      // ссылка и околоссылочный текст
      // добавляете 
      		//....
      		$item_output .= '(' . $count_category  . ')';
      		$item_output .= '</a>';
      		//....
      • Владимир 29 апреля 2015 #

        Извините меня. Но я только пытаюсь понять как этот Walker код работает. У меня появились только скобки () а дальше я так понимаю мне нужно изменить в этом коде:

        global $wp_query;  
        $count_category = '';
        if($item->object == 'category')  { 
        $cat_id = $item->object_id;
        $count_category = get_category($cat_id)->category_count;
        }

        так чтобы моя произвольная таксономия показывала количество записей?
        я использую такой код в function.php :

        <pre lang="htaccess">add_action( 'init', 'prowp_publishing_taxonomy' );
        function prowp_publishing_taxonomy() {
        	$labels = array(
        		'name' 				=> 'Категории',
        		'singular_name' 	=> 'Категория',
        		'search_items' 		=> 'Найти Категорию',
        		'all_items' 		=> 'Все категории',
        		'parent_item' 		=> 'Родительская категория',
        		'parent_item_colon' => 'Родительские категории:',
        		'edit_item' 		=> 'Редактировать категорию',
        		'update_item' 		=> 'обновить категорию',
        		'add_new_item' 		=> 'Добавить новую категорию',
        		'new_item_name' 	=> 'Новое название категории',
        		'menu_name' 		=> 'Категории'
        	);
        	$args =array(
        		'labels'	   => $labels,
        		'hierarchical' => true,
        		'query_var'	   => true,
        		'rewrite' 	   => true
        	);
        	register_taxonomy( 'type', 'publishings', $args );
        }
        • VRS 29 апреля 2015 #

          Ну да)

          if($item->object == 'category')  
           
          //меняете на
           
           if($item->object == 'publishings')
          • Владимир 29 апреля 2015 #

            Вот только этого результата не дает.

        • VRS 29 апреля 2015 #

          Ну можно было бы немного подумать самостоятельно))). Если у Вас не категория, значит нужна аналогичная функция для произвольной таксономии. Вот же у Миши https://misha.blog/blog/wordpress/get_terms.html#args

          Вместо

          $count_category = get_category($cat_id)->category_count;

          Пробуйте

          $count_category = get_terms('publishings', 'fields=count');
          • Владимир 29 апреля 2015 #

            Попытаюсь разобраться сам. Как добьюсь решений выложу результат. спасибо. )

  • Владимир 9 июля 2015 #

    В sidebar вложен виджет произвольное меню в котором выбирается нужное меню из списка уже созданных (меню1, меню2, меню3 ...). Задача чтобы в произвольном меню на странице1 было меню1, на странице2 было меню2 и т.д. Возможно ли с помощью True_Walker_Nav_Menu это реализовать? Извините, если что не так написал, я еще мало разбираюсь в этом.

    • Миша 9 июля 2015 #

      У меня для вас хорошая новость — колдовать с волкером не придется, вот эта функция вам поможет the_widget() ну и условные теги, is_page() я так полагаю.

      • Владимир 9 июля 2015 #

        Только у меня их три. Как определить в какой?

      • Владимир 9 июля 2015 #
        if ( is_page( 'сраница1' ) ) {	
        	if ( !function_exists('dynamic_sidebar') || !dynamic_sidebar('Контент слева') ) {  the_widget( 'WP_Nav_Menu_Widget', array('nav_menu' => 'Меню1_1') );} 
        	if ( !function_exists('dynamic_sidebar') || !dynamic_sidebar('Контент центр') ) { the_widget( 'WP_Nav_Menu_Widget', array('nav_menu' => 'Меню1_2') );} 
        	if ( !function_exists('dynamic_sidebar') || !dynamic_sidebar('Контент справа') ) { the_widget( 'WP_Nav_Menu_Widget', array('nav_menu' => 'Меню1_3') ); } 
        }
        if ( is_page( 'сраница2' ) ) {	
        	if ( !function_exists('dynamic_sidebar') || !dynamic_sidebar('Контент слева') ) {  the_widget( 'WP_Nav_Menu_Widget', array('nav_menu' => 'Меню2_1') );} 
        	if ( !function_exists('dynamic_sidebar') || !dynamic_sidebar('Контент центр') ) { the_widget( 'WP_Nav_Menu_Widget', array('nav_menu' => 'Меню2_2') );} 
        	if ( !function_exists('dynamic_sidebar') || !dynamic_sidebar('Контент справа') ) { the_widget( 'WP_Nav_Menu_Widget', array('nav_menu' => 'Меню2_3') ); } 
        }
        if ( is_page( 'сраница3' ) ) {	
        	if ( !function_exists('dynamic_sidebar') || !dynamic_sidebar('Контент слева') ) {  the_widget( 'WP_Nav_Menu_Widget', array('nav_menu' => 'Меню3_1') );} 
        	if ( !function_exists('dynamic_sidebar') || !dynamic_sidebar('Контент центр') ) { the_widget( 'WP_Nav_Menu_Widget', array('nav_menu' => 'Меню3_2') );} 
        	if ( !function_exists('dynamic_sidebar') || !dynamic_sidebar('Контент справа') ) { the_widget( 'WP_Nav_Menu_Widget', array('nav_menu' => 'Меню3_3') ); } 
        }

        Я правильно думаю? подскажите пожалуйста

        • Владимир 9 июля 2015 #

          почему то не работает((

        • Владимир 9 июля 2015 #

          я в php не силен. туда я вставляю код для замены меню в виджите? файл page.php место где надо вывести меню

  • Владимир 9 июля 2015 #

    Спасибо. Я так полагаю надо так?

    is_page( 'Страница1' ) the_widget( 'WP_Nav_Menu_Widget', array('nav_menu' => 'Меню1') );
    is_page( 'Страница2' ) the_widget( 'WP_Nav_Menu_Widget', array('nav_menu' => 'Меню2') );
    • Миша 10 июля 2015 #

      Примерно так, да.

      if( is_page( 'Страница1' ) ) the_widget( 'WP_Nav_Menu_Widget', array('nav_menu' => 'Меню1') );
  • VRS 17 июля 2015 #

    Привет, Миш).
    Ты не в курсе, есть ли способ сортировать wp_nav_menu как wp_page_menu по post_title ?

  • JaRule 17 августа 2015 #

    Здравствуйте Михаил!
    Сразу оговорюсь что опыта разработки на php у меня очень мало, а с классами на нем и вовсе не работал никогда. Вопрос такой: изначально мне нужно сделать верхнее меню в теме которая таковые не поддерживает. Я сделал все по тексту, и класс вставил тоже. Меню вверху появилось, только оно идет в столбик (пункт1, строчкой ниже пункт2 и т.д.) а как сделать чтобы оно было в строчку (пункт1, правее пункт2 и т.д.), и где именно в этом классе вставлять html-тэги для меню (цвет, шрифт и т.д. и т.п.), и если это возможно то хотя бы с маленьким примером. Буду признателен за ответ.

    • Миша 17 августа 2015 #

      Здравствуйте! Такие вещи делаются через CSS, например:

      li.menu-item{
      display: inline-block; /* элементы меню должны будут встать в строчку */
      }
      • JaRule 17 августа 2015 #

        Большое спасибо за ответ, по самому блоку понятно, а куда его вставлять? Если в сам класс то куда именно (в начало, в конец)? Если в другое место то в какой файл и какую часть?

        • Миша 17 августа 2015 #

          style.css в папке темы.

  • Сергей 16 декабря 2015 #

    Здравствуйте, Михаил!

    Зарегестрировал меню, назначил свои стили, но вот какая проблема:
    У меня есть страница "Новости", где выводятся посты.

    При нажатии на вкладку "Новости" кнопке назначаются активные стили (становится темной), но, как только я нажимаю на ссылку поста кнопка "Новости" перестает быть активной.
    Например, на Вашем блоге кнопка "Блог" продолжает оставаться выделенной при просмотре статей. Хотелось бы реализовать похожее решение. Странно, но в интернете не получилось найти нужной информации.
    Заранее спасибо за ответ!

    • Сергей 16 декабря 2015 #

      P.S. Сначала хотел выводить отдельные шаблоны header-{slug}.php, но подумал, что есть другое решение

      • Миша 19 декабря 2015 #

        Тут нужно просто в постах стили дописать.

        Самый простой вариант — открываете single.php и добавляете туда стили активной вкладки "Новости".

  • Алексей 17 декабря 2015 #

    здравствуйте! Подскажите пожалуйста
    Возникла необходимость одному пункту меню (контакты) задать класс Сделать это можно прописав класс в пункте меню Класс прописываю но он у меня не отображается
    в файле функции есть код добавляющий описание в меню может в нем проблема!?

    class Menu_Description extends Walker_Nav_Menu {
    	function start_el(&$output, $item, $depth, $args) {
    		global $wp_query;
    		$indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
    	       	$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) );
    		$class_names = ' class="' . esc_attr( $class_names ) . '"';
        		$class_names = ( $item->current == 1 ) ? ' class="current-menu-item"' : '';
            $output .= $indent . '<li itemprop="name"' . $id . $value . $class_names .'>';
            // атрибуты элемента, title="", rel="", target="" и href=""
    		$attributes = ! empty( $item->attr_title ) ? ' title="' . esc_attr( $item->attr_title ) .'"' : '';
    		$attributes .= ! empty( $item->target ) ? ' target="' . esc_attr( $item->target ) .'"' : '';
    		$attributes .= ! empty( $item->xfn ) ? ' rel="' . esc_attr( $item->xfn ) .'"' : '';
    		$attributes .= ! empty( $item->url ) ? ' href="' . esc_attr( $item->url ) .'"' : '';
     
    		$item_output = $args->before;
    		$item_output .= '<a itemprop="url" '. $attributes .'>';
    		$item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
    		$item_output .= '<br /><span class="sub">' . $item->description . '</span>';
    		$item_output .= '</a>';
    		$item_output .= $args->after;
    		$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
    	}
    }

    Меню вывожу в шапке сайта так

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

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

    • Миша 19 декабря 2015 #

      Здравствуйте!
      Я этот код писал давно и возможно есть какие-то недочёты.

      Попробуйте строку:

      $class_names = ( $item->current == 1 ) ? ' class="current-menu-item"' : '';

      переместить на две строчки вверх.

      • Алексей 19 декабря 2015 #

        В админке вордпресса в меню можно задать дополнительные пункты "отношение к ссылке" "открывать в новом окне" все они присваиваются

        // атрибуты элемента, title="", rel="", target="" и href=""
        		$attributes = ! empty( $item->attr_title ) ? ' title="' . esc_attr( $item->attr_title ) .'"' : '';
        		$attributes .= ! empty( $item->target ) ? ' target="' . esc_attr( $item->target ) .'"' : '';
        		$attributes .= ! empty( $item->xfn ) ? ' rel="' . esc_attr( $item->xfn ) .'"' : '';
        		$attributes .= ! empty( $item->url ) ? ' href="' . esc_attr( $item->url ) .'"' : ''

        А "класс сss" когда прописываем он присваивается можно ли как то изменить чтобы класс присваивался

  • Руслан 30 января 2016 #

    Здравствуйте, такая проблема с которой столкнулся, нужен такой вид меню:

    <li class="active"><a href="#">Главная</a></li>
    <li class="divider-vertical"></li>
    <li><a href="#">Акция</a></li>
    <li class="divider-vertical"></li>
    <li><a href="#">Продукция</a></li>

    Т.е. после каждого пункта списка добавлять еще список пустой но с определенными классом:

    <li class="divider-vertical"></li>

    кроме последнего пункта
    Вопрос: Как узнать что это последний пункт меню и поставить в условии не выводить "

    <li class="divider-vertical"></li>

    " после конца списка?

    • Миша 31 января 2016 #

      Здравствуйте, если я правильно понял вашу задачу, почему бы вам не решить её при помощи CSS псевдоэлементов :before или :after?

      • Руслан 31 января 2016 #

        Такая задумка была у верстальщика, что по пустому элементу списка

        <li class="divider-vertical"></li>

        ставится разделитель пунктов. Ну это не столь важно данную проблему можно решить двумя способами с помощью

        https://misha.blog/blog/wordpress/wp_get_nav_menu_items.html

        или же с помощью данного Walker только в админке меню добавляем любой класс к последнему элементу и тогда мы его уже можем вычислить, пример:

        $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
         
        		if($item->classes[0]!=='last'){
        	 		$output .= '<li class="divider-vertical"></li>';
        		}

        Я не писал весь код но в конце вот, что добавил. может кому интересно будет как понять что дошел до последнего пункта меню.

  • Лешка 19 ноября 2019 #

    Как всегда у Миши ничего не работает, сделал 50% процентов - дальше ебитесь сами с костылями

    • Миша 22 ноября 2019 #

      Возможно выпрямление ваших рук может поправить ситуацию 🤔

    • Виталий 9 декабря 2019 #

      Отлично все работает. Вникайте, а не тупо копипасте. Хотя, если даже правильно скопировать, то все прекрасно работает.

      • Миша 9 декабря 2019 #

        Спс🔥

        Видимо я забыл упомянуть, что нужно вставлять после открывающего тега <?php
        😁

  • Игорь 3 января 2020 #

    Здравствуйте!
    В мобильной версии сайта при открытии меню появилось предупреждение:
    Warning: Declaration of YOOtheme\Theme\Wordpress\MenuWalker::walk($elements, $max_depth) should be compatible with Walker::walk($elements, $max_depth, ...$args) in /home/i/igorvovf/lock-open.ru/public_html/wp-content/themes/yootheme/vendor/yootheme/theme/platforms/wordpress/src/Wordpress/MenuWalker.php on line 9

    Не подскажите где искать решение проблемы?

    • Миша 3 января 2020 #

      Добрый день и с Новым годом! 🎄

      Спасибо за адекватный вопрос! Обновил урок 🔥💪

      А когда это появилось, вы не заметили? Предполагаю, что после обновления на 5.3? Смотрите, в вашей ситуации, я так понимаю вы используете определённую тему какого-то разработчика, есть два решения:

      1) (наиболее правильное) Подождать, пока они выпустят обновление темы с отключенным WP_DEBUG в файле wp-config.php. Для ускорения процесса можно попробовать написать в Yootheme

      2) Вы можете залезать в код и просто сделать то, что просят в Warning, а именно на строчке 9 указываем точно такие же аргументы, как в рекомендации Walker::walk($elements, $max_depth, ...$args)

      • Игорь 3 января 2020 #

        И вас с Новым годом Михаил!!!

        Честно говоря не я заметил, подсказали что ошибка вылазит. Тема не обновляется.
        Тоже предполагаю что после обновления, плюс еще свежую РНР установил.

        В коде, на строчке 9 сейчас следующее:
        class MenuWalker extends \Walker_Nav_Menu

        Михаил, укажите пожалуйста куда конкретнее вставить:
        Walker::walk($elements, $max_depth, ...$args)

  • Клим 10 января 2020 #

    Здравствуйте Миша!
    Большое спасибо за детальный урок информация в вашем блоге очень помогает. Делаю первые шаги в WP в основном все методом "научного тыка"))

    На данный момент споткнулся с вставкой кода с сайта Сodepen. Уже третий день не могу победить. Копирую код и стили, но почему-то их не подхватывает.
    Не могли бы вы объяснить пошагово, как подключить на сайт WP код и стили с Сodepen
    Вот пример полноэкранного меню которое хочу подключить https://codepen.io/flpespinoza/pen/eJjjdx

    • Миша 10 января 2020 #

      Здравствуйте! Рад помочь! 🙃

      Я обычно удаляю комментарии не по теме, но только для вас:
      Шаг 1. Не вставлять SCSS

      • Клим 11 января 2020 #

        Вот где корень зла! 🙂 Спасибо

        • Миша 11 января 2020 #

          Пожалуйста! 👍🙃 Рад, что поняли меня с полуслова

          • Клим 12 января 2020 #

            По вашей наводке стал курить SCSS и понял, что для моих задач не нужен WP :-), а достаточно будет Bootstrap или даже Джекил.
            Но если у вас возникнет когда-то желание написать статью по вставке кодов с Codepen в WP — думаю она будет пользоваться не меньшей популярностью, тк даже при глубоком поиске google ничего такого не выдает.

            • Миша 12 января 2020 #

              Не знаю, что такое джекил, но желаю вам удачи! 💪

              • Клим 12 января 2020 #

                https://en.wikipedia.org/wiki/Jekyll_(software)
                Еще раз спасибо, у вас отличный блог!

              • Миша 12 января 2020 #

                Спасибо! 😊

  • Анди__Анди 6 марта 2020 #

    низкий поклон за статью. Доброе дело делаете !!!

  • Игнат 20 марта 2020 #

    можно ли подсветить ссылку в меню archive-$posttype.php, если мы находимся на странице taxnonomy-$taxonomy.php ? posttype и tax взаимосвязаны

  • Комрон 27 марта 2020 #

    Здравствуйте, Миша помогите с этим меню который находиться в футере. как создать и что вы рекомендуете.
    https://cdn1.savepice.ru/uploads/2020/3/27/d67ad3217953c5d4d6caff775fc69c90-full.png

    • Миша 27 марта 2020 #

      Здравствуйте!

      Думаю лучше всего выводить через WP_Query.

      • Комрон 28 марта 2020 #

        Дорогой друг можете пример приводить

        • Миша 28 марта 2020 #

          А там есть все примеры

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

Если вы хотите добавить код, не забудьте обернуть его в <pre lang="php"></pre>, в случае несоблюдения этого условия в 99% случаях ваш коммент будет удалён, а автор заблокирован. Печалька.