Skip to main content

Автор: vyatka

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

Очень долго многие ждали эту возможность и вот наконец то это случилось, нативный способ добавления своих собственных полей в пункты меню WordPress!

C релизом WordPress 5.4 стали доступны новые хуки: wp_nav_menu_item_custom_fields и wp_nav_menu_item_custom_fields_customize_template первый для экрана редактирования меню, второй для Customizer.

Посмотрим на практическом примере как это работает. Создадим небольшой учебный плагин custom menu fields, который будет добавлять к пункту меню наш текст.

Для этого идем в папку с плагинами, создаем там папку custom-menu-fields и внутри нее одноименный файл custom-menu-fields.php

Далее нам нужно прописать заголовок, чтоб WordPress определил что это плагин:

<?php
/**
 * Plugin Name:     Custom menu fields
 * Description:     Test new hooks for WordPress 5.4
 */

Этого достаточно чтоб WP обнаружил его. Далее соответственно пропишем функции.

Цепляемся к новому хуку и добавим свое текстовое поле.

/**
* Add our custom field
*
* @param  int $item_id 
* @params obj $item - the menu item
* @params array $args
*/
function hook_custom_fields( $item_id, $item ) {

wp_nonce_field( 'custom_menu_meta_nonce', '_custom_menu_meta_nonce_name' );
$custom_menu_meta = get_post_meta( $item_id, '_custom_menu_meta', true );
?>

<input type="hidden" name="custom-menu-meta-nonce" value="<?php echo wp_create_nonce( 'custom-menu-meta-name' ); ?>" />
<div class="field-custom_menu_meta description-wide" style="margin: 5px 0;">
<span class="description"><?php _e( "Extra Field", 'custom-menu-meta' ); ?></span>
<br />
<input type="hidden" class="nav-menu-id" value="<?php echo $item_id ;?>" />
<div class="logged-input-holder">
<input type="text" name="custom_menu_meta[<?php echo $item_id ;?>]" id="custom-menu-meta-for-<?php echo $item_id ;?>" value="<?php echo esc_attr( $custom_menu_meta ); ?>" />
<label for="custom-menu-meta-for-<?php echo $item_id ;?>">
<?php _e( 'Custom menu text', 'custom-menu-meta'); ?>
</label>
</div>
</div>

<?php
}
add_action( 'wp_nav_menu_item_custom_fields', 'hook_custom_fields', 10, 2 );

Т.к. в WordPress пункт меню это тоже свой тип записей то работа с post_meta для него в целом не отличается от любого другого типа записи.

/**
* Save the menu item meta
* 
* @param int $menu_id
* @param int $menu_item_db_id	
*/
function hook_nav_update( $menu_id, $menu_item_db_id ) {

// Verify this came from our screen and with proper authorization.
if ( ! isset( $_POST['_custom_menu_meta_nonce_name'] ) || ! wp_verify_nonce( $_POST['_custom_menu_meta_nonce_name'], 'custom_menu_meta_nonce' ) ) {
		return $menu_id;
	}
if ( isset( $_POST['custom_menu_meta'][$menu_item_db_id]  ) ) {
  $sanitized_data = sanitize_text_field( $_POST['custom_menu_meta'][$menu_item_db_id] );
  update_post_meta( $menu_item_db_id, '_custom_menu_meta', $sanitized_data );
    } else {
  delete_post_meta( $menu_item_db_id, '_custom_menu_meta' );
    }
}
add_action( 'wp_update_nav_menu_item', 'hook_nav_update', 10, 2 );

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

P.S. Это лишь пример, вы можете делать сами что угодно с этими данными в зависимости от вашей задачи.

/**
* Displays text on the front-end.
*
* @param string   $title The menu item's title.
* @param WP_Post  $item  The current menu item.
* @return string      
*/
function hook_custom_menu_title( $title, $item ) {

if( is_object( $item ) && isset( $item->ID ) ) {
  $custom_menu_meta = get_post_meta( $item->ID, '_custom_menu_meta', true );
  if ( ! empty( $custom_menu_meta ) ) {
    $title .= ' - ' . $custom_menu_meta;
  }
 }
  return $title;
}

add_filter( 'nav_menu_item_title', 'hook_custom_menu_title', 10, 2 );

Вот как-то так. Это был пример использования новых возможностей WordPress 5.4 на примере добавления своего поля к пункту меню.

В примере не рассмотрен второй хук, который работает в Customizer, но это уже оставляю уже разобраться вам самим.