В этом уроке хочу познакомить вас с двумя новыми хуками, появившимися в WordPress 5.4, которые позволят вам добавить какой-нибудь текст или HTML в интерфейс редактирования элемента меню в админке и кастомайзере. А если можно добавить HTML, то можно добавить какие-то поля 🤔
Если вы не до конца разобрались с функционалом меню WordPress, то обязательно посмотрите мой видеоурок по меню.
Экшен-хук wp_nav_menu_item_custom_fields
срабатывает сразу после того, как выводятся все поля при редактировании конкретного элемента меню и имеет следующие параметры:
$item_id
– ID элемента меню,$item
– объект элемента меню,$depth
– уровень вложенности элемента меню,$args
– объект дополнительных аргументов,$id
– ID самого меню, а не элемента.
То есть у нас есть возможность передать все эти параметры в прикреплённую к хуку функцию, например так:
add_action( 'wp_nav_menu_item_custom_fields', 'true_hello', 10, 5 ); function true_hello( $item_id, $item, $depth, $args, $id ) { echo 'Приветик'; }
И в итоге в админке мы получаем:
Сам я не очень часто пользуюсь кастомайзером, как-то добавлял поля для своего плагина туда и в то время написал гайд по кастомайзеру, с тех пор мне практически не приходилось его использовать. Однако есть плагины, которые его используют и не имеют альтернативных настроек в админке WordPress, например один такой плагин многие знают – WooCommerce.
На этом пункте особо подробно не буду останавливаться, скажу лишь, что у хука wp_nav_menu_item_custom_fields_customize_template
нет никаких параметров, однако внутри HTML, который вы выведете этим хуком, вы можете использовать такие конструкции как {{ data.menu_item_id }}
или <# if ( 'custom' === data.item_type ) { #>
.
Я бы написал об этом отдельный урок, и напишу, когда (если) буду чаще пользоваться кастомайзером.
Пример
Так как я сам недавно запилил на сайте два видеокурса (раз и два) и настраивал отображение сайта для зарегистрированных и незарегистрированных пользователей, то актуальнее всего будет добавить в элемент меню, который мы с вами будем выводить на примере условия отображения для авторизованных пользователей, например так:
add_action( 'wp_nav_menu_item_custom_fields', 'true_menu_field', 10, 5 ); function true_menu_field( $item_id, $item, $depth, $args, $id ) { // можете сюда также вкинуть wp_nonce_field и его проверку в следующем шаге $is_logged_in = get_post_meta( $item_id, '_menu_loggedin', true ); echo '<p class="description"> <label> <input type="checkbox" ' . checked( 'yes', $is_logged_in, false ) . ' name="menu-item-loggedin[' . $item_id . ']"> Только для зарегистрированных пользователей </label> </p>'; }
- Как видно на строчке 7, работа с метаданными меню по сути как и работа с мета обычных типов записей, мы даже используем наверняка знакомую вам get_post_meta().
- На строке 11 функция checked() позволяет сравнить два значения и, в случае их совпадения, сразу вывести
checked='checked'
для поля чекбокса.
Сохранение полей
Тут тоже всё делается обычным хуком, очень похожим на принцип действия save_post
.
add_action( 'wp_update_nav_menu_item', 'true_update_menu', 10, 2 ); function true_update_menu( $menu_id, $menu_item_db_id ) { // если добавляли nonce-поле, то тут его валидация $meta_value = isset( $_POST[ 'menu-item-loggedin' ][ $menu_item_db_id ] ) && 'on' == $_POST[ 'menu-item-loggedin' ][ $menu_item_db_id ] ? 'yes' : 'no'; update_post_meta( $menu_item_db_id, '_menu_loggedin', $meta_value ); }
Супер, чекбокс добавили, сохраняться тоже должен норм, теперь нужно как-то задействовать всё это на сайте.
Про функцию wp_get_nav_menu_items() у меня есть отдельный пост на сайте, а сейчас вкратце покажу, как интегрировать в неё нашу проверку на авторизованного пользователя при помощи is_user_logged_in().
if( $menu_items = wp_get_nav_menu_items( $menu ) ) { foreach ( $menu_items as $key => $menu_item ) { if( ! is_user_logged_in() && 'yes' == get_post_meta( $menu_item->ID, '_menu_loggedin', true ) ) { continue; } // ... тут идёт вывод элемента меню } }
В самой функции wp_nav_menu() мы не можем так легко залезть в тело цикла и прописать туда своё условие.
Что же делать? Использовать класс волкера, про который вы у меня можете почитать здесь и посмотреть видеоурок здесь.
Наше условие нужно прописать в самом начале метода волкера start_el()
function start_el( &$output, $item, $depth = 0, $args = NULL, $id = 0 ) { if( ! is_user_logged_in() && 'yes' == get_post_meta( $item->ID, '_menu_loggedin', true ) ) { return; } // ... }
Источник: misha.blog