WordPress позволяет использовать так называемые классы Walker для обхода и отображения элементов в иерархической структуре. В этом посте мы узнаем, как создавать, реализовывать и настраивать наш собственный класс Walker для настройки вывода нашего меню.
Наиболее известное использование классов Walker в WordPress для меню, но на самом деле WordPress использует классы Walker для целого ряда случаев, например, для вывода иерархии таксономии, иерархии комментариев [wp_list_pages](https://developer.wordpress.org/reference/functions/wp_list_pages/)()
и [wp_list_categories](https://developer.wordpress.org/reference/functions/wp_list_categories/)()
. Все они расширяют общий Walker
класс. Мы расширим тот, Walker_Nav_Menu
который используется для меню в WordPress.
Поскольку мы расширяем другой класс, нам нужно добавить только те функции, которые мы хотим переопределить. Если функция не существует в нашем классе, WordPress вместо этого запустит функцию родительского класса (класс, который мы расширяем).
Подготовка
Вы можете добавить свой класс Walker в свои файлы плагинов, темы function.php
или любой файл PHP, включенный functions.php
(для более чистого кода). Вы начинаете с определения вашего класса по имени по вашему выбору (убедитесь, что имя класса уникально, и оно включает возможные имена классов в ядре WordPress!), расширяя Walker_Nav_Menu
:
class AWP_Menu_Walker extends Walker_Nav_Menu {
}
Чтобы указать WordPress использовать наш ходок, мы определяем это в наших [wp_nav_menu](https://developer.wordpress.org/reference/functions/wp_nav_menu/)()
вызовах. Эта функция отвечает за вывод меню и наверняка у вас есть хотя бы одна в вашей теме для главного меню.
В массив аргументов wp_nav_menu()
вы добавляете новый элемент с ключом «ходок» и создаете новый экземпляр вашего класса ходока следующим образом:
Если вы обновите свой сайт, вы не увидите никаких изменений. Это связано с тем, что наш класс не переопределяет ни одну из родительских функций, и, таким образом, WordPress просто запускает обычные функции обходчика меню при выводе меню, точно так же, как до того, как мы сказали ему использовать наш обходчик.
Ниже приведены функции, которые вы можете добавить в свой пользовательский класс ходока, чтобы переопределить функции родительского класса Walker_Nav_Menu
:
Первые четыре — это функции, которые просто отвечают за вывод, и все они требуют добавления к строке — первой переменной параметра. Важно знать, что вы echo
ничего здесь не делаете, все должно быть построено как струна.
start_lvl
Функция start_lvl
отвечает за вывод HTML для начала нового уровня. Короче говоря, он должен выводить начальный файл <ul>
.
function start_lvl(&$output, $depth=0, $args=null) { }
Первый параметр, $output
передаваемый по ссылке, представляет собой строку, к которой вы добавите вывод. $depth
представляет собой целое число, сигнализирующее, на каком уровне вы находитесь; 0 для верхнего уровня, 1 для прямого потомка верхнего уровня и так далее. $args
является объектом всех аргументов, представленных в wp_nav_menu()
.
end_lvl
Функция end_lvl
отвечает за вывод HTML в конце уровня. Обычно это только закрытие </ul>
.
function end_lvl(&$output, $depth=0, $args=null) { }
Параметры точно такие же, как и start_lvl
выше.
start_el
Эта функция отвечает за вывод HTML-кода каждого элемента. Короче говоря, он должен выводить начало <li>
и <a>
тег с заголовком ссылки внутри.
function start_el(&$output, $item, $depth=0, $args=null, $id=0) { }
Первый аргумент, $output
как обычно, представляет собой строку, к которой вы добавляете вывод. Второй аргумент, $item
, является объектом пункта меню, и именно здесь вы получите большую часть данных для вывода пункта меню. Если ссылка меню является пунктом меню поста, здесь вы получите объект поста. Независимо от типа меню, вы также получите некоторые дополнительные полезные элементы; такие как classes
, url
, title
и description
.
Третий аргумент, $depth
, представляет собой целое число, указывающее, на каком уровне мы находимся. Уровень 0 — это верхний уровень, 1 — прямой потомок верхнего уровня и так далее. Четвертый аргумент, $args
, является объектом всех аргументов, предоставляемых wp_nav_menu()
. Пятый параметр, $id
, является идентификатором текущего пункта меню.
end_el
Функция end_el
отвечает за вывод закрытия элемента. Обычно он просто выводит </li>
тег.
function end_el(&$output, $item, $depth=0, $args=null) { }
Аргументы для end_el
те же, что и start_el
выше, за исключением того, что функция не имеет пятого параметра, $id
.
display_element
Эта функция display_element
унаследована от общего Walker
класса и является функцией, отвечающей за обход. Это функция, которая по очереди вызывает все вышеперечисленные функции.
Я включаю это здесь, потому что в некоторых случаях, например, если вы хотите предотвратить обход всей ветки, вы должны использовать эту функцию для этого.
function display_element($element, &$children_elements, $max_depth, $depth, $args, &$output) { }
Первый аргумент $element
— это объект пункта меню — это то, что передается вниз, как и $item
в приведенных выше функциях. Второй аргумент, $children_elements
переданный по ссылке, содержит все дочерние элементы, через которые будет проходить эта функция. $max_depth
, третий аргумент, представляет собой целое число, указывающее, насколько глубоко мы должны пройти, а четвертый аргумент, $depth
, представляет собой глубину, на которой мы сейчас находимся. Пятый аргумент $args
— это аргументы, переданные функции, вызвавшей обходчик (для меню это будут аргументы, предоставленные функции wp_nav_menu()
), а последний аргумент, $output
переданный по ссылке, — это выходные данные, которые передаются в качестве первого аргумента во всех из вышеперечисленных функций.
Изменение вывода каждого элемента
В приведенном выше обзоре вы должны увидеть, что функция start_el()
отвечает за вывод HTML для одного элемента меню. Давайте начнем с переопределения этой функции в нашем классе ходока на простом примере.
Пример: запрет добавления ссылок для элементов ‘#’
Давайте удостоверимся, что все #
ссылки ‘ ‘ получают <span>
элемент вместо тега ссылки, чтобы избежать обновления страницы.
Мы начнем элемент, добавив <li>
тег к $output
. Мы хотим убедиться, что классы WordPress по умолчанию (например, «элемент меню», «элемент меню-имеет-детей» и т. д.), а также классы, введенные вручную в редакторе меню, добавляются в наш элемент списка. Мы склеиваем классы, представленные в виде массива, $item->classes
используя функцию PHP, [implode](https://www.php.net/manual/en/function.implode.php)()
разделяя каждый элемент пробелом.
В строках 5-9 и 13-17 мы обрабатываем условный вывод элемента-обертки. Мы выводим <a>
тег, если URL-адрес элемента не является ‘ #
‘, и в этом случае вместо этого мы предоставляем <span>
тег. В строке №11 мы просто выводим текст ссылки, который находится в $item->title
.
Это все, что нам нужно, чтобы убедиться, что все элементы меню, которые имеют ‘ #
‘ в качестве URL-адреса, не кликабельны!
Если вы делаете это в стилизованной теме, имейте в виду, что вы можете потерять некоторые стили, если тема стилизовала <a>
тег напрямую. Вы можете решить эту проблему, изменив стиль и, возможно, добавив класс к элементу span.
Например, здесь вы можете вывести описание меню. Это существует, но не активировано по умолчанию. В редакторе меню WordPress вам нужно нажать «Параметры экрана» в правом верхнем углу и поставить галочку для отображения «Описание»:
Это позволяет пользователю ввести описание для каждого элемента. Вы можете вывести это описание в свой класс ходока. Допустим, вы хотите показать описание только для элементов верхнего уровня, так как это часть дизайна вашей темы. Вы можете просто проверить, $item
есть ли описание, и если оно $depth
равно 0, например:
Пример: добавление выпадающих курсоров
Более распространенным и полезным примером является добавление «каретки», значка, который сигнализирует о том, что этот пункт меню имеет раскрывающееся меню (имеет дочерние элементы).
Пример кареток в действии — за «Блог» и «Новости»
Вам нужно будет выяснить вывод вашего HTML-кода. В моем случае я вывожу <i>
элемент с определенными классами для красивой стрелки вниз, доступной в библиотеке Fontawesome, которая предоставляет тысячи значков. Вы также хотите убедиться, что эта каретка выводит только те элементы, у которых есть дочерние элементы. Лучший способ, который я нашел, чтобы выяснить, есть ли у текущего элемента дочерние элементы, — это сослаться на объект Walker (да, который является самим нашим Walker, но также и классами, которые он расширяет!) в $args
, и проверить логическое значение has_children
. Вывод каретки так же прост, как:
Полный класс ходока будет выглядеть так:
И это все, что вам нужно для обеспечения того, чтобы в вашем меню появились красивые значки курсора на родительских элементах, а #
ссылки ‘ ‘ не были кликабельными.
Если вы хотите, чтобы значок вставки изменился, например, на стрелку вверх, когда раскрывающийся список активен, вам нужно будет добавить это с помощью Javascript в свою тему.
Как показывают приведенные выше примеры, вы можете манипулировать выводом по своему усмотрению, основываясь на любых условных выражениях. Например, вы можете изменить вывод в зависимости от того, присутствует ли определенный класс (например, класс, введенный вручную в редакторе меню), выполнив поиск класса в $item->classes
, или вы можете манипулировать (например, использовать заглавные буквы) выводимый текст элемента, указанный в $item->title
.
Хочу отметить еще одну полезную вещь. Помните, что $args содержит все аргументы, предоставляемые wp_nav_menu()
. Это включает в себя, например theme_location
, и другие, поэтому, если вы можете изменить вывод только для определенных мест темы — например, для главного меню. Но на самом деле вы можете предоставить любые пользовательские аргументы!
Скажем, вы выводите одно и то же меню несколько раз, например, одно для рабочего стола и еще раз для мобильного. Или вы хотите, чтобы ваш ходок манипулировал элементами только тогда, когда они выводятся wp_nav_menu()
в вашей теме, а не когда меню добавляется через виджет? Возможно, вы хотите, чтобы ваш ходок в этих случаях обрабатывал выходные данные по-другому?
Вы можете указать любые настраиваемые аргументы для wp_nav_menu()
. В качестве простого примера я добавлю логическое значение ‘ show_carets
‘ к аргументам, чтобы гарантировать, что каретки добавляются только в тех случаях, когда я этого хочу – вместо того, чтобы мой класс Walker добавлял каретки во все меню.
Затем я могу просто изменить часть кода с добавлением вставки выше (строки 19-21) на проверку того show_carets
, присутствует или нет в $args
, например так:
Вы можете добавить любые аргументы, которые хотите, чтобы ваш ходок настраивал только те меню, которые вы хотите. Например, простые логические значения для разных случаев, например is_mobile_menu
, или что-то еще, что вам нужно.
И это все. Не стесняйтесь экспериментировать и дайте мне знать, если у вас есть какие-либо вопросы или предложения ниже!