Програмно додайте меню навігації та елементи меню


41

За допомогою функцій API я хочу визначити нове меню навігації , вибрати його в поточній темі, а потім вставити кілька сторінок як пункти меню. Це потрібно зробити, наприклад, для активації теми.

Через (помірно болісний) процес зворотної інженерії база даних вставляє та оновлює після встановлення меню та елементів навігації вручну, я склав наступні кроки, де "footer-nav" - ідентифікатор слугу меню навігації I " м створюю:

if (!term_exists('footer-nav', 'nav_menu')) {

    $menu = wp_insert_term('Footer nav', 'nav_menu', array('slug' => 'footer-nav'));

    // Select this menu in the current theme
    update_option('theme_mods_'.get_current_theme(), array("nav_menu_locations" => array("primary" => $menu['term_id'])));

    // Insert new page
    $page = wp_insert_post(array('post_title' => 'Blog',
                                 'post_content' => '',
                                 'post_status' => 'publish',
                                 'post_type' => 'page'));

    // Insert new nav_menu_item
    $nav_item = wp_insert_post(array('post_title' => 'News',
                                     'post_content' => '',
                                     'post_status' => 'publish',
                                     'post_type' => 'nav_menu_item'));


    add_post_meta($nav_item, '_menu_item_type', 'post_type');
    add_post_meta($nav_item, '_menu_item_menu_item_parent', '0');
    add_post_meta($nav_item, '_menu_item_object_id', $page);
    add_post_meta($nav_item, '_menu_item_object', 'page');
    add_post_meta($nav_item, '_menu_item_target', '');
    add_post_meta($nav_item, '_menu_item_classes', 'a:1:{i:0;s:0:"";}');
    add_post_meta($nav_item, '_menu_item_xfn', '');
    add_post_meta($nav_item, '_menu_item_url', '');

    wp_set_object_terms($nav_item, 'footer-nav', 'nav_menu');
}

Це, здається, працює, але:

  • це надійний і елегантний спосіб зробити це?
  • я пропускаю щось абсолютно очевидне, що могло б зробити все це в одному рядку коду?

Відповіді:


43

Я можу вас нерозуміти, але чому б не використати wp_create_nav_menu()?

Наприклад, це те, що я роблю, щоб створити користувацьке меню BuddyPress, коли виявляю ВР як активну:

    $menuname = $lblg_themename . ' BuddyPress Menu';
$bpmenulocation = 'lblgbpmenu';
// Does the menu exist already?
$menu_exists = wp_get_nav_menu_object( $menuname );

// If it doesn't exist, let's create it.
if( !$menu_exists){
    $menu_id = wp_create_nav_menu($menuname);

    // Set up default BuddyPress links and add them to the menu.
    wp_update_nav_menu_item($menu_id, 0, array(
        'menu-item-title' =>  __('Home'),
        'menu-item-classes' => 'home',
        'menu-item-url' => home_url( '/' ), 
        'menu-item-status' => 'publish'));

    wp_update_nav_menu_item($menu_id, 0, array(
        'menu-item-title' =>  __('Activity'),
        'menu-item-classes' => 'activity',
        'menu-item-url' => home_url( '/activity/' ), 
        'menu-item-status' => 'publish'));

    wp_update_nav_menu_item($menu_id, 0, array(
        'menu-item-title' =>  __('Members'),
        'menu-item-classes' => 'members',
        'menu-item-url' => home_url( '/members/' ), 
        'menu-item-status' => 'publish'));

    wp_update_nav_menu_item($menu_id, 0, array(
        'menu-item-title' =>  __('Groups'),
        'menu-item-classes' => 'groups',
        'menu-item-url' => home_url( '/groups/' ), 
        'menu-item-status' => 'publish'));

    wp_update_nav_menu_item($menu_id, 0, array(
        'menu-item-title' =>  __('Forums'),
        'menu-item-classes' => 'forums',
        'menu-item-url' => home_url( '/forums/' ), 
        'menu-item-status' => 'publish'));

    // Grab the theme locations and assign our newly-created menu
    // to the BuddyPress menu location.
    if( !has_nav_menu( $bpmenulocation ) ){
        $locations = get_theme_mod('nav_menu_locations');
        $locations[$bpmenulocation] = $menu_id;
        set_theme_mod( 'nav_menu_locations', $locations );
    }

Я не знав про цю функцію. Так, я думаю, це зробить вищезазначений код набагато коротшим. Я думаю, що мені слід вийти за рамки Codex і зануритися у фактичний код, оскільки я вважаю, що функції API часто, як у цьому випадку, занадто низькі. Дякую!
julien_c

@julien_c, якщо це вирішено, позначте це як таке, щоб дати змогу тим, хто приходить після вас, скористатися тут.
mor7ifer

Я просто хочу насправді перевірити це в реальному житті, тому я впевнений, що він робить те, що я хочу. Я пам’ятаю, щоб позначити це як вирішене, як тільки я закінчу!
julien_c

3
Якщо ви бачите такі корисні функції, яких немає в кодексі, корисно додати їх (yay wiki) = p
Tom J Nowell

Вибачте, мені знадобилося стільки часу, щоб перевірити, чи спрацювало це в моєму випадку. Відповідь прийнято! Крім того, ви визначаєте елементи меню спеціальних посилань , я додав відповідь нижче, щоб визначити посилання на сторінку (що буде більш надійним щодо змін у URL-адресах).
julien_c

12

Як доповнення до прихильника ZaMoose, ось як би ви створили пункт меню " Сторінка " (а не " Спеціальний "):

wp_update_nav_menu_item($menu_id, 0, array('menu-item-title' => 'About',
                                           'menu-item-object' => 'page',
                                           'menu-item-object-id' => get_page_by_path('about')->ID,
                                           'menu-item-type' => 'post_type',
                                           'menu-item-status' => 'publish'));

Якщо припустимо, ви знаєте лише слизьку сторінку, наприклад.


9

У мене є кілька питань із прийнятою відповіддю - це не робить його неправильним, але я опублікую свій власний код, під яким я вважаю, що для деяких людей може бути кращий результат, оскільки я мав те саме запитання, але хотів зробити те саме річ з меншим кодом.

По-перше, вищевказаний код створює елементи навігації типу "URL", що добре для деяких людей, але я хочу посилатися на PAGES, а не на URL-адреси, оскільки це важлива особливість навігації в WordPress, а клієнти неминуче переміщують речі, тому я ніколи не використовую URL-адресу тип елемента нав.

Крім того, розміщений код обробляє лише плоский масив дітей. Я створив функцію для рекурсивного оголошення нових елементів наві, зберігання їх повернутих метаданих (головним чином ідентифікатор після створення в циклі) та параметр для прийому дітей.

Просто редагуйте, $nav_items_to_addа решта обробляється рекурсивно. У кожному масиві є 3 необхідних ключа. По-перше, ключем масиву є слизький, так 'shop' => array( ... )це те, що ви хочете для сторінки зі слизом shop. ['title']це те, як елемент навігації буде позначений на передньому кінці. pathце шлях до сторінки в рамках ієрархії сторінок WordPress, тож це ідентично слизу, якщо сторінка є батьком вищого рівня, і якби це shopбуло дитиною, homeто це було б 'path' => 'home/shop'.

Останній необов’язковий ключ масиву - це те, ['parent']де ви можете оголосити інший ключ у масиві як батьківський для поточного. Важливо зазначити, що елементи додаються рекурсивно, тому батько повинен існувати ще до того, як ви спробуєте створити дитину. Це означає, що декларація повинна відбуватися для батьківського елемента елемента nav, перш ніж це діти.

    $locations = get_nav_menu_locations();

    if (isset($locations['primary_navigation'])) {
        $menu_id = $locations['primary_navigation'];

        $new_menu_obj = array();

        $nav_items_to_add = array(
                'shop' => array(
                    'title' => 'Shop',
                    'path' => 'shop',
                    ),
                'shop_l2' => array(
                    'title' => 'Shop',
                    'path' => 'shop',
                    'parent' => 'shop',
                    ),
                'cart' => array(
                    'title' => 'Cart',
                    'path' => 'shop/cart',
                    'parent' => 'shop',
                    ),
                'checkout' => array(
                    'title' => 'Checkout',
                    'path' => 'shop/checkout',
                    'parent' => 'shop',
                    ),
                'my-account' => array(
                    'title' => 'My Account',
                    'path' => 'shop/my-account',
                    'parent' => 'shop',
                    ),
                'lost-password' => array(
                    'title' => 'Lost Password',
                    'path' => 'shop/my-account/lost-password',
                    'parent' => 'my-account',
                    ),
                'edit-address' => array(
                    'title' => 'Edit My Address',
                    'path' => 'shop/my-account/edit-address',
                    'parent' => 'my-account',
                    ),
            );

    foreach ( $nav_items_to_add as $slug => $nav_item ) {
        $new_menu_obj[$slug] = array();
        if ( array_key_exists( 'parent', $nav_item ) )
            $new_menu_obj[$slug]['parent'] = $nav_item['parent'];
        $new_menu_obj[$slug]['id'] = wp_update_nav_menu_item($menu_id, 0,  array(
                'menu-item-title' => $nav_item['title'],
                'menu-item-object' => 'page',
                'menu-item-parent-id' => $new_menu_obj[ $nav_item['parent'] ]['id'],
                'menu-item-object-id' => get_page_by_path( $nav_item['path'] )->ID,
                'menu-item-type' => 'post_type',
                'menu-item-status' => 'publish')
        );
    }

    }

2

Для додавання пункту меню програмно. ви можете зачепити wp_nav_menu_itemsфільтр. розмістіть нижче код у вашій темі function.php, щоб додати пункт меню входу / виходу в головне меню. 'Основний' - це ім'я / ідентифікатор зареєстрованого меню.

/**
 * Add login logout menu item in the main menu.
 * ===========================================
 */

add_filter( 'wp_nav_menu_items', 'lunchbox_add_loginout_link', 10, 2 );
function lunchbox_add_loginout_link( $items, $args ) {
    /**
     * If menu primary menu is set & user is logged in.
     */
    if ( is_user_logged_in() && $args->theme_location == 'primary' ) {
        $items .= '<li><a href="'. wp_logout_url() .'">Log Out</a></li>';
    }
    /**
     * Else display login menu item.
     */
    elseif ( !is_user_logged_in() && $args->theme_location == 'primary' ) {
        $items .= '<li><a href="'. site_url('wp-login.php') .'">Log In</a></li>';
    }
    return $items;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.