Меню в 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 {
	/**
	 * @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) {
		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 );

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

Подпишитесь, чтобы раз в неделю получать свежие статьи с блога по email.

Посты по теме:

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

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

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

    • Миша23 октября 2014 в 07:10 #

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

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

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

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

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

  • Григорий14 ноября 2014 в 13:11 #

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

  • Толя15 декабря 2014 в 11:12 #

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

  • VRS4 марта 2015 в 05:03 #

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

    • VRS4 марта 2015 в 06:03 #

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

  • Алексей8 апреля 2015 в 06:04 #

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

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

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

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

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

    • Миша8 апреля 2015 в 07:04 #

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

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

      Станет:

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

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

  • Dennis9 апреля 2015 в 19:04 #

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

    • Алексей9 апреля 2015 в 22:04 #

      если вас не интересует 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;}
      • Dennis10 апреля 2015 в 06:04 #

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

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

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

          • Алексей10 апреля 2015 в 13:04 #

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                  1
                  2
                  3
                  
                  $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 в 14:01 #

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

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

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

  • VRS17 апреля 2015 в 17:04 #

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

    • Миша18 апреля 2015 в 08:04 #

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

      • VRS18 апреля 2015 в 22:04 #

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

        • Миша19 апреля 2015 в 10:04 #

          Я рад, что мой блог помогает людям)

          Если трудностей с кодом не возникнет, но в следующий понедельник (27.04) пост будет на англ. блоге, и соответственно в пятницу (1.05) - на русском. Понимаю, что это довольно долго, и возможно у тебя к этому времени уже появится решение — прост у меня уже всё распланировано на этой неделе, раньше не смогу.

          • VRS19 апреля 2015 в 13:04 #

            Пока проблему с меню мы решили совместно с хостером - увеличением значений suhosin (как предлагали разработчики в том багрепорте), правда скорость обработки запроса 1,5-2 минуты.

  • Владимир29 апреля 2015 в 09:04 #

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

  • Владимир29 апреля 2015 в 13:04 #

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

  • Владимир29 апреля 2015 в 13:04 #

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

    • VRS29 апреля 2015 в 15:04 #

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

      В 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 в 20:04 #

        Извините меня. Но я только пытаюсь понять как этот 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 );
        }
        • VRS29 апреля 2015 в 21:04 #

          Ну да)

          if($item->object == 'category')  
           
          //меняете на
           
           if($item->object == 'publishings')
        • VRS29 апреля 2015 в 21:04 #

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

          Вместо

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

          Пробуйте

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

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

  • Владимир9 июля 2015 в 08:07 #

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

    • Миша9 июля 2015 в 09:07 #

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

      • Владимир9 июля 2015 в 09:07 #

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

      • Владимир9 июля 2015 в 09:07 #
        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 в 09:07 #

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

    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') );
  • VRS17 июля 2015 в 17:07 #

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

  • JaRule17 августа 2015 в 01:08 #

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

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

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

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

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

  • Сергей16 декабря 2015 в 10:12 #

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

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

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

    • Сергей16 декабря 2015 в 10:12 #

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

      • Миша19 декабря 2015 в 10:12 #

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

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

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

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

    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 в 10:12 #

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

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

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

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

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

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

        // атрибуты элемента, 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 в 16:01 #

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

    <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 в 10:01 #

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

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

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

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

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

        https://truemisha.ru/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>';
        		}

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

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

phpjsHTMLCSSSQLПросто код
  Для того, чтобы оставить комментарий, пожалуйста, зарегистрируйтесь или авторизуйтесь на сайте.
Получайте новости блога по email или следите за мной в социальных сетях.
  • Владимир: и на третьей строке не хватает скобки ) закрывающей if :)

  • Миша: Добрый вечер! Рекомендую получить ID пользователя через функцию get_current_user_id().

  • Дмитрий: Миша, подскажите пожалуйста, я использую такой редирект, но он не срабатывает: add_action( 'template_redirect', funct...

  • Миша: Ну как не определена - это аргумент функции. Или я просто вас не до конца понимаю.

  • Артем: Ага, понял. Вот только почему $args? Она же нигде не определена, по логике должна быть переменная $true_field_params или...