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()
ви додаєте новий елемент із ключем «walker» і створюєте новий екземпляр вашого класу walker таким чином:
Якщо ви оновите свій сайт, ви не побачите жодних змін. Це пов’язано з тим, що наш клас не перевизначає жодну з батьківських функцій, і, таким чином, WordPress просто запускає звичайні функції проходження меню під час виведення меню, як і раніше, коли ми сказали йому використовувати наш крокувальник.
Нижче наведено функції, які ви можете додати до свого спеціального класу Walker, щоб замінити функції батьківського класу 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 для окремого елемента меню. Давайте почнемо з перевизначення цієї функції в нашому класі walker на простому прикладі.
Приклад: заборона додавання посилань для елементів «#».
Давайте переконаємося, що будь-які #
посилання «» отримують <span>
елемент замість тегу посилання, щоб уникнути оновлення сторінки.
Ми почнемо елемент, додавши <li>
тег до $output
. Ми хочемо переконатися, що стандартні класи WordPress (наприклад, «menu-item», «menu-item-has-children» тощо), а також класи, введені вручну в редакторі меню, додаються до нашого елемента списку. Ми склеюємо класи, надані як масив, за $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
, і перевірити boolean 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
, або щось інше, що вам потрібно.
І це приблизно все. Не соромтеся експериментувати та дайте мені знати, якщо у вас виникнуть запитання чи пропозиції нижче!