Добавление иконок к пунктам меню wordpress
Всем привет. Я не так давно изучаю WP. Хочу добавить иконки к каждому пункту меню, но уже 2 день сижу и не знаю что с этим делать. Временно поставила плагин "menu image", но хочу сделать это без него используя код :) Что можно почитать или как можно реализовать это?

Ответы (2 шт):
Скорее всего не актуально, но может кому то поможет
Сразу стоит отметить, что я не стал добавлять выбор изображения. В моей задаче оптимальным было указать id SVG иконки из спрайта, которая будет вставляться инлайново с помощью <use>.
Так у нас меньше заморочек и сохраняется гибкость в цветах и размерах, которые спокойно можно задать в CSS и менять при разных состояниях.
В любом случае думаю вы без особых проблем сможете аналогично добавить нужные вам дополнительные поля.
Рекомендую сначала посмотреть результат в прикрепленном скриншоте (внизу), чтобы лучше понимать код. Лучше всё скопировать в свой редактор
Первым делом используем хук wp_nav_menu_item_custom_fields. Добавляем всё в function.php
<? function vs_iconav_custom_fields($item_id, $item)
{
// Если кастомные поля вам нужны во всех меню - можете удалить создание массива элементов и условие if (in_array($item, $iconav_all_menu_items)) :. Не забудьте endif тоже удалить
$iconav_all_menu_items = array(); //массив пунктов меню для которых будет возможность указать иконку
$iconav_menu_ids = array(42, 50);// массив с id меню. Добавьте id меню в которых вам нужны кастомные поля. Например Главное меню id - 42, Меню футер id - 50
// собираем элементы всех указанных меню в один массив
foreach ($iconav_menu_ids as $id) {
$iconav_all_menu_items = array_merge($iconav_all_menu_items, wp_get_nav_menu_items($id));
}
// если текущий элемент есть в нашем массиве - добавляем для него поля
if (in_array($item, $iconav_all_menu_items)) :
wp_nonce_field('iconav_meta_nonce', '_iconav_meta_nonce_name');
// обратите внимание на _iconav_meta. По этому названию вы будете получать свои данные с полей. Вы можете назвать по своему например _customnav_meta, только не забудьте поменять везде название
$iconav_meta = get_post_meta($item_id, '_iconav_meta', true); // получаем мета поля текущего элемента (пункта меню)
// если метаполе существует и содержит данные, забираем их (В начале естественно они будут пустые)
$icon = $iconav_meta && $iconav_meta['icon'] ? esc_attr($iconav_meta['icon']) : ''; // в моем случае название иконки
$size = $iconav_meta && $iconav_meta['size'] ? esc_attr($iconav_meta['size']) : ''; // размер для иконки одним полем. По хорошему width и height надо будет сделать, но пока так. В CSS правлю если надо
$disabled = $iconav_meta && $iconav_meta['disabled'] ? 'checked' : '';// это был просто чекбокс показывающий, что пункт меню пока недоступен
// продумайте свой список переменных. К примеру из вашего скриншота это могли быть $menu_img $img_hover $img_size $img_position...
// дальше пишем разметку, которая будет отображаться в пунктах меню. Смотрим на скрин для лучшего понимания
//Я особо не заморачивался и просто под себя быстро всё корректировал лишь бы было. Возможно некоторые элементы лишние, не уверен насчет input hidden, в остальном вроде всё норм
?>
<div class="field-icon_meta description-wide" style="margin: 5px 0;">
<span class="description"><?php _e("Название иконки", '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="icon_meta[<?php echo $item_id; ?>]" id="custom-menu-meta-for-<?php echo $item_id; ?>" value="<?php echo $icon; ?>" style="width: 100%"/>
</div>
<span class="description" style="color: green"><?php _e("*svg иконка вставляется из sprite.svg", 'custom-menu-meta'); ?></span>
</div>
<br>
<br>
<div class="field_meta description-wide" style="margin: 5px 0;">
<span class="description"><?php _e("Размер иконки (px)", '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="size_meta[<?php echo $item_id; ?>]" id="size-meta-for-<?php echo $item_id; ?>" value="<?php echo $size ?>" style="width: 30%; margin-right: 90px"/>
<input type="checkbox" name="disabled_meta[<?php echo $item_id; ?>]" id="disabled-meta-for-<?php echo $item_id; ?>" <?php echo $disabled; ?>/>
<label for="disabled-meta-for-<?php echo $item_id; ?>">Отключить пункт меню</label>
</div>
</div>
<?php
endif;
}
// не забываем использовать хук со своей функцией. Внимательно с названием функции
add_action('wp_nav_menu_item_custom_fields', 'vs_iconav_custom_fields', 10, 2);
Теперь используем хук wp_update_nav_menu_item для обновления данных в наших метаполях после сохранения изменений в меню
function vs_iconav_update($menu_id, $menu_item_db_id)
{
// Так понял проверяем, что мы авторизованы и обновляется меню с кастомными полями. Оставлю оригинал на инглише
// Verify this came from our screen and with proper authorization.
if (!isset($_POST['_iconav_meta_nonce_name']) || !wp_verify_nonce($_POST['_iconav_meta_nonce_name'], 'iconav_meta_nonce')) {
return $menu_id;
}
// здесь проверяются данные именно с инпута по его name. Если при обновлении он был не пустой, берем все данные и обновляем
// Вы можете проверять по любому важному для вас полю или по хорошему каждое поле проверять отдельно. В моем случае без иконки остальное неважно было
if (isset($_POST['icon_meta'][$menu_item_db_id])) {
// Соответственно здесь будет тот же список полей, который вы укажите в предыдущей функции и будете использовать в разметке
$sanitized_data['icon'] = sanitize_text_field($_POST['icon_meta'][$menu_item_db_id]);
$sanitized_data['size'] = sanitize_text_field($_POST['size_meta'][$menu_item_db_id]);
$sanitized_data['disabled'] = sanitize_text_field($_POST['disabled_meta'][$menu_item_db_id]);
// обновляем все поля. А вот и наше название _iconav_meta
update_post_meta($menu_item_db_id, '_iconav_meta', $sanitized_data);
} else {
delete_post_meta($menu_item_db_id, '_iconav_meta');
}
}
add_action('wp_update_nav_menu_item', 'vs_iconav_update', 10, 2);
Вот и всё. По идее если вы скопируете весь код в ваш functions.php и укажете id своего меню, у вас уже должны будут появиться эти поля (id можно в адресной строке посмотреть, когда редактируете меню).
Использую я это при создании кастомного вывода меню с помощью Walker_Nav_Menu{}. Среди всего прочего кода меню, примеры которого вы легко можете найти, поля я получаю следующим образом
<?php
// Берем наши поля _iconav_meta
$iconav_meta = get_post_meta($item->ID, '_iconav_meta', true);
// Ну и все значения получаем так - $iconav_meta['название поля']
$icon_url = get_template_directory_uri() . '/img/icons/sprite.svg#' . $iconav_meta['icon'];
$size = $iconav_meta && $iconav_meta['size'] ? esc_attr($iconav_meta['size']) : '';
P.S. Писал код давно, раньше чем этот вопрос появился и к сожалению первоисточник откуда взял пример не укажу. Не вникал во все тонкости работы, но вроде не сложно разобраться, постарался основные моменты описать. Да и вообще я больше фронтендер, сильно не ругайтесь)
Вероятно код будет не идеальный и всё такое, но он работает, использовал на нескольких проектах и буквально сейчас он понадобился. Собственно поэтому я здесь
Вот тут описано полное решение задачи как добавить иконку в меню без плагина: https://i-love-web-it.com/wordpress/articles/dobavleniye-izobrazheniy-ikonok-k-punktam-menyu-v-wordpress-bez-plagina/
