В этой статье подробно разберем, как создать иерархическое меню в WordPress с многоуровневой структурой, а также добавить кастомные атрибуты к элементам меню для расширения функциональности и удобства навигации. Такой подход помогает сделать меню более информативным и гибким, а также улучшить UX на сайте.
Основы создания многоуровневого меню в WordPress
WordPress по умолчанию поддерживает меню с подменю, которые можно создавать в админке через Внешний вид > Меню. Однако для более сложных и кастомных иерархий часто требуется доработка кода.
Многоуровневое меню — это меню, где под каждым пунктом могут быть вложенные пункты, организованные в дерево. Для правильного отображения подменю тема должна поддерживать вывод вложенных элементов, обычно через функцию wp_nav_menu() с правильно настроенным walker-классом.
Пример базового вызова меню с поддержкой подменю:
wp_nav_menu(array(
'theme_location' => 'primary',
'menu_class' => 'main-menu',
'depth' => 3 // максимальная глубина подменю
));Параметр depth указывает, сколько уровней вложенности будет отображаться.
Добавление кастомных атрибутов и метаданных к элементам меню
Иногда нужно добавить дополнительные данные к пунктам меню: иконки, подсказки, специальные классы или data-атрибуты. WordPress позволяет расширять поля меню с помощью фильтров и пользовательских walker-ов.
Расширение полей меню через фильтр walker_nav_menu_start_el
Этот фильтр позволяет модифицировать HTML каждого элемента меню перед выводом. Например, чтобы добавить иконку из кастомного поля:
add_filter('walker_nav_menu_start_el', 'wphierarchy_add_icon_to_menu_item', 10, 4);
function wphierarchy_add_icon_to_menu_item($item_output, $item, $depth, $args) {
$icon = get_post_meta($item->ID, '_menu_item_icon', true);
if ($icon) {
$icon_html = '<i class="' . esc_attr($icon) . '"></i> ';
$item_output = $icon_html . $item_output;
}
return $item_output;
}В этом примере мы получаем значение иконки из метаполя _menu_item_icon и добавляем HTML иконки перед названием пункта.
Добавление пользовательских полей в админку меню
Чтобы добавить поле для ввода иконки в админке меню, используют хук wp_nav_menu_item_custom_fields (доступен с WP 5.4). Пример:
add_action('wp_nav_menu_item_custom_fields', 'wphierarchy_add_custom_menu_fields', 10, 4);
function wphierarchy_add_custom_menu_fields($item_id, $item, $depth, $args) {
$icon = get_post_meta($item_id, '_menu_item_icon', true);
?>
<p class="field-icon description description-wide">
<label for="edit-menu-item-icon-<?php echo $item_id; ?>">Иконка (класс)<br>
<input type="text" id="edit-menu-item-icon-<?php echo $item_id; ?>" class="widefat code edit-menu-item-icon" name="menu-item-icon[<?php echo $item_id; ?>]" value="<?php echo esc_attr($icon); ?>">
</label>
</p>
<?php
}После добавления поля нужно сохранить данные при сохранении меню:
add_action('wp_update_nav_menu_item', 'wphierarchy_save_custom_menu_fields', 10, 3);
function wphierarchy_save_custom_menu_fields($menu_id, $menu_item_db_id, $args) {
if (isset($_POST['menu-item-icon'][$menu_item_db_id])) {
$icon_value = sanitize_text_field($_POST['menu-item-icon'][$menu_item_db_id]);
update_post_meta($menu_item_db_id, '_menu_item_icon', $icon_value);
}
}Использование кастомного walker класса для сложных иерархий меню
Если нужно гибко контролировать вывод меню — например, добавить дополнительную обертку, произвольные атрибуты, или изменить структуру HTML — пишут свой класс, наследующийся от Walker_Nav_Menu.
Пример кастомного walker, который добавляет data-атрибут с ID пункта меню:
class WPHierarchy_Walker_Nav_Menu extends Walker_Nav_Menu {
function start_el(&$output, $item, $depth=0, $args=null, $id=0) {
$data_id = 'data-menu-id="' . esc_attr($item->ID) . '"';
$classes = empty($item->classes) ? array() : (array) $item->classes;
$class_names = join(' ', apply_filters('nav_menu_css_class', array_filter($classes), $item, $args));
$class_names = $class_names ? ' class="' . esc_attr($class_names) . '"' : '';
$output .= '<li ' . $data_id . $class_names . '>';
$attributes = ' href="' . esc_attr($item->url) . '"';
$item_output = '<a' . $attributes . '>' . apply_filters('the_title', $item->title, $item->ID) . '</a>';
$output .= apply_filters('walker_nav_menu_start_el', $item_output, $item, $depth, $args);
}
function end_el(&$output, $item, $depth=0, $args=null) {
$output .= "</li>";
}
}Использовать класс в вызове меню:
wp_nav_menu(array(
'theme_location' => 'primary',
'walker' => new WPHierarchy_Walker_Nav_Menu(),
'depth' => 3
));Практические советы и готовые решения для иерархии меню
1. Учитывайте адаптивность меню. Многоуровневые меню часто сложно корректно отобразить на мобильных устройствах. Используйте CSS и JS для управления раскрытием подменю.
2. Используйте плагины для расширения меню. Например, плагин Clearfy Pro помогает оптимизировать меню и убрать лишние элементы.
3. Автоматизируйте создание меню с помощью кода. Если структура меню зависит от пользовательских таксономий или иерархий постов, используйте функции для динамического создания пунктов меню.
Пример функции для динамического добавления пунктов меню из кастомной таксономии:
function wphierarchy_add_terms_to_menu($items, $args) {
if ($args->theme_location != 'primary') return $items;
$terms = get_terms(array('taxonomy' => 'category', 'hide_empty' => false));
foreach ($terms as $term) {
$menu_item = new stdClass();
$menu_item->ID = 100000 + $term->term_id; // уникальный ID
$menu_item->title = $term->name;
$menu_item->url = get_term_link($term);
$menu_item->menu_item_parent = 0;
$menu_item->type = '';
$menu_item->object = '';
$menu_item->object_id = '';
$menu_item->classes = array();
$items[] = $menu_item;
}
return $items;
}
add_filter('wp_nav_menu_objects', 'wphierarchy_add_terms_to_menu', 10, 2);Заключение по теме
Создание иерархического меню в WordPress с подменю и кастомными атрибутами — задача, требующая внимательности к деталям и грамотного использования API. Мы рассмотрели, как расширить меню через поля в админке, использовать фильтры и собственные walker-классы для гибкой настройки вывода. Это позволит сделать навигацию на сайте более удобной и функциональной без потери производительности.