Как программно добавить пункты в пользовательское меню WordPress

23 апр. 2011 г., 19:24:11
Просмотры: 44.4K
Голосов: 23

Есть ли способ программно добавить пункты пользовательского меню при первой установке темы? Я создаю тему, которая автоматически создает некоторые общие страницы при установке. Поэтому мне нужно знать, могу ли я также добавить их в пользовательское меню 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, ничего не происходит на странице меню в панели администратора, но существующие пункты меню исчезают на сайте!

0
Все ответы на вопрос 4
14
25

Проблема с вашим кодом в том, что он не добавляет ссылки в меню, а только в вывод меню, поэтому используется фильтр (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
24 апр. 2011 г. 06:03:11
Комментарии

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

Sisir Sisir
24 апр. 2011 г. 20:42:31

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

Bainternet Bainternet
25 апр. 2011 г. 03:12:57

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

Sisir Sisir
28 апр. 2011 г. 22:36:24

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

Sisir Sisir
28 апр. 2011 г. 22:48:38

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

Bainternet Bainternet
29 апр. 2011 г. 03:26:01

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

Sisir Sisir
29 апр. 2011 г. 19:35:00

@Sisir: какое название у вашего расположения меню?

Bainternet Bainternet
29 апр. 2011 г. 21:46:52

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

Sisir Sisir
30 апр. 2011 г. 10:54:09

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

Bainternet Bainternet
30 апр. 2011 г. 15:04:16

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

Sisir Sisir
1 мая 2011 г. 14:19:45

Рад, что у вас получилось.

Bainternet Bainternet
1 мая 2011 г. 17:00:05

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

Sisir Sisir
23 мая 2011 г. 23:50:13

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

Clawsy Clawsy
12 мая 2016 г. 09:46:10

Даже спустя 9 лет информация все еще актуальна!

Beee Beee
6 дек. 2020 г. 02:54:57
Показать остальные 9 комментариев
1
12

Ваш исходный код был очень близок к правильному решению, и я считаю, что это длинное решение от @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), который был необходим для выполнения проверки.

1 авг. 2012 г. 13:43:05
Комментарии

Как бы вы установили расположение пункта меню с помощью этого метода?

User User
4 нояб. 2014 г. 03:05:11
0

В WordPress 3.4.2 есть ошибка:

https://github.com/WordPress/WordPress/commit/ae96b842f9f55ecfb22da705a4902b9d25580259#wp-includes/nav-menu.php

Необходимо вручную создать связь термина:

$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 для простого создания меню.

26 нояб. 2012 г. 16:29:38
0

Для справки, текущий пользователь должен иметь права на добавление терминов. Мои элементы меню были созданы, но не добавлены в таблицу wp_terms_relationship до того, как я добавил вызов wp_set_current_user(1);

2 авг. 2013 г. 16:43:18