Как программно добавить пункты в пользовательское меню WordPress
Есть ли способ программно добавить пункты пользовательского меню при первой установке темы? Я создаю тему, которая автоматически создает некоторые общие страницы при установке. Поэтому мне нужно знать, могу ли я также добавить их в пользовательское меню WordPress, чтобы клиенту не нужно было добавлять их вручную?
Другими словами: как программно вставить/создать пункт пользовательского меню?
Дайте знать, если что-то непонятно. Ссылка на соответствующую страницу документации приветствуется. Спасибо!
обновление: попробовал код отсюда Targeting specific menu with wp_nav_menu_items
Регистрация меню:
function register_my_menus() {
register_nav_menus(
array('main-menu' => __( 'Главное меню' ) )
);
}
add_action( 'init', 'register_my_menus' );
Использование в шаблоне:
<?php wp_nav_menu( array( 'theme_location' => 'main-menu' ) ); ?>
Код для добавления новых пунктов:
function new_nav_menu_items($items) {
if( $args->theme_location == 'main-menu' ){
$homelink = '<li class="home"><a href="' . home_url( '/' ) . '">' . __('Главная') . '</a></li>';
$items = $homelink . $items;
return $items;
}
}
add_filter( 'wp_nav_menu_items', 'new_nav_menu_items', 10, 2 );
Когда добавляю код для добавления новых пунктов меню в файл functions.php
, ничего не происходит на странице меню в панели администратора, но существующие пункты меню исчезают на сайте!

Проблема с вашим кодом в том, что он не добавляет ссылки в меню, а только в вывод меню, поэтому используется фильтр (add_filter). Фактически, вы просто фильтруете вывод меню, и даже если у вас нет меню, ваша ссылка будет отображаться с используемым кодом. Но чтобы создать ссылку и добавить её в меню, вы можете использовать этот код:
$run_once = get_option('menu_check');
if (!$run_once){
//дайте вашему меню имя
$name = 'основное меню темы';
//создаем меню
$menu_id = wp_create_nav_menu($name);
//получаем объект меню по его имени
$menu = get_term_by( 'name', $name, 'nav_menu' );
//затем добавляем фактическую ссылку/пункт меню, и это делается для каждого элемента, который нужно добавить
wp_update_nav_menu_item($menu->term_id, 0, array(
'menu-item-title' => __('Главная'),
'menu-item-classes' => 'home',
'menu-item-url' => home_url( '/' ),
'menu-item-status' => 'publish'));
//затем устанавливаем желаемое расположение в теме
$locations = get_theme_mod('nav_menu_locations');
$locations['main-menu'] = $menu->term_id;
set_theme_mod( 'nav_menu_locations', $locations );
//затем обновляем опцию menu_check, чтобы этот код выполнялся только один раз
update_option('menu_check', true);
}
Я добавил комментарии повсюду, чтобы сделать код понятнее.
Чтобы создать дочернюю страницу/подстраницу/меню второго уровня (как бы вы это ни называли), вам просто нужно установить menu-item-parent-id
в новом элементе, например:
//создаем пункт меню верхнего уровня (Главная)
$top_menu = wp_update_nav_menu_item($menu->term_id, 0, array(
'menu-item-title' => __('Главная'),
'menu-item-classes' => 'home',
'menu-item-url' => home_url( '/' ),
'menu-item-status' => 'publish'
'menu-item-parent-id' => 0,
));
//Подменю (первый дочерний элемент)
$first_child = wp_update_nav_menu_item($menu->term_id, 0, array(
'menu-item-title' => __('Первый_дочерний'),
'menu-item-classes' => 'home',
'menu-item-url' => home_url( '/' ),
'menu-item-status' => 'publish'
'menu-item-parent-id' => $top_menu,
));
//Подподменю (второй дочерний элемент)
$Second_child = wp_update_nav_menu_item($menu->term_id, 0, array(
'menu-item-title' => __('Второй_дочерний'),
'menu-item-classes' => 'home',
'menu-item-url' => home_url( '/' ),
'menu-item-status' => 'publish'
'menu-item-parent-id' => $first_child,
));
Также вы можете установить позицию с помощью кода, используя menu-item-position
, и, я думаю, это делается так:
- Первый элемент - 'menu-item-position' => 1
- Первый дочерний элемент первого элемента - 'menu-item-position' => 1
- Второй дочерний элемент первого элемента - 'menu-item-position' => 1
- Первый дочерний элемент второго дочернего элемента первого элемента - 'menu-item-position' => 1
- Второй элемент - 'menu-item-position' => 2
- 3-й элемент - 'menu-item-position' => 3
- 4-й элемент - 'menu-item-position' => 4

Это именно те функции, которые я искал :) В кодексе их не было :( Ещё один вопрос - как добавить дочерний элемент к пункту "Главная". Я дам знать, как только доберусь до компьютера. Спасибо!

@Sisir: я обновил пример, показывающий как создавать дочерние страницы

@Bainternet: при первом запуске кода получил ошибку Fatal error: Cannot use object of type stdClass as array in C:\wamp\www\citystir\wp-admin\menu.php on line 25
. Но меню создаётся, и после обновления страницы всё работает, однако в разделе Внешний вид -> Меню Расположение в теме
ничего не отображается. Мы уже очень близки :) Спасибо!

@Bainternet: Похоже, код выдаёт ошибку при попытке выполнить $locations = get_theme_mod('nav_menu_locations');
. Поэтому код до этой строки (всё, что связано с добавлением меню) выполняется, а код после (установка нужного расположения в теме) — нет.

@Sisir: код работает нормально, какое у вас название расположения меню в теме и покажите точный код, который вы используете — посмотрю, смогу ли помочь.

@Bainternet: Вот http://pastebin.com/Px16q43a. Использовал pastebin.

я использовал этот код в навигационном меню wp_nav_menu( array( 'theme_location' => 'main-menu' ) );
, так что предполагаю, что название расположения темы - main-menu
, верно?

да, но вам всё равно нужно зарегистрировать это расположение темы с помощью register_nav_menu( $location, $description );
прежде чем пытаться назначить меню для этого расположения.

@Bainternet : Спасибо! Название расположения темы теперь отображается. Но ошибка все еще была, пока я не поместил код в функцию и не добавил эту функцию на страницу настроек темы. Теперь она будет запускаться только при нажатии кнопки. Похоже, что таким образом ошибка исчезла. Теперь все работает отлично. Спасибо за всю вашу помощь. Надеюсь, вы всегда будете отвечать на мои вопросы ;)

@Bainternet: Привет, мне снова пришлось вас побеспокоить :) С помощью функции wp_update_nav_menu_item()
пункты меню добавляются как пользовательские ссылки. Есть ли способ, с помощью которого я могу добавлять пункты меню типа "запись" или "страница"? Дело в том, что когда я обновляю постоянные ссылки, пользовательские ссылки не обновляются. Но если это пункты меню типа "страница", они бы обновлялись автоматически. Думаю, я достаточно понятно объяснил. Спасибо!

@Bainternet: Привет, атрибут menu-item-position
должен инкрементироваться от верхнего пункта меню до нижнего, независимо от наличия подпунктов. Я нашел это здесь: http://www.acousticwebdesign.net/wordpress/how-to-create-wordpress-3-navigation-menus-in-your-theme-or-plugin-code/.

Ваш исходный код был очень близок к правильному решению, и я считаю, что это длинное решение от @Bainternet (без обид) является избыточным. Вместо этого посмотрите на этот вариант:
function new_nav_menu_items($items, $args) {
if( $args->theme_location == 'primary' ){
$homelink = '<li class="home"><a href="' . home_url( '/' ) . '">' . __('Home') . '</a></li>';
$items = $homelink . $items;
}
return $items;
}
add_filter( 'wp_nav_menu_items', 'new_nav_menu_items', 10, 2 );
Ваша единственная проблема заключалась в том, что вы не возвращали $items после того, как функция проверяла правильное меню, и вам не хватало второго аргумента обратного вызова ($args), который был необходим для выполнения проверки.

В WordPress 3.4.2 есть ошибка:
Необходимо вручную создать связь термина:
$menu = wp_get_nav_menu_object('top menu');
$id = wp_update_nav_menu_item($menu->term_id, 0, $data);
if ($menu->term_id && (!is_object_in_term($id, 'nav_menu', (int)$menu->term_id))) {
wp_set_post_terms($id, array((int)$this->id), 'nav_menu');
}
Смотрите https://gist.github.com/4148529 для примера класса Menu для простого создания меню.
