Programowo dodaj menu nawigacyjne i elementy menu

41

Poprzez funkcje API chcę zdefiniować nowe menu Nawigacji , wybrać je w bieżącym motywie, a następnie wstawić kilka Stron jako elementy menu. Należy to zrobić na przykład podczas aktywacji motywu.

Poprzez (umiarkowanie bolesny) proces inżynierii wstecznej wstawianie i aktualizowanie bazy danych po ręcznym skonfigurowaniu menu i elementów nawigacji, poskładałem następujące kroki, w których „stopka-nawigacja” to identyfikator ślimaka menu nawigacji I ” m tworzę:

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');
}

To wydaje się działać, ale:

  • czy to solidny i elegancki sposób na zrobienie tego?
  • czy brakuje mi czegoś całkowicie oczywistego, co zrobiłoby to wszystko w jednym wierszu kodu?
julien_c
źródło

Odpowiedzi:

42

Mogę cię źle rozumieć, ale dlaczego nie użyć wp_create_nav_menu()?

Na przykład to robię, aby utworzyć niestandardowe menu BuddyPress, gdy wykryję BP jako aktywne:

    $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 );
    }
ZaMoose
źródło
Nie wiedziałem o tej funkcji. Tak, chyba spowoduje to, że powyższy kod będzie znacznie krótszy. Chyba powinienem wyjść poza Kodeks i zagłębić się w rzeczywisty kod, ponieważ uważam, że funkcje API są często, tak jak w tym przypadku, zbyt niskie. Dzięki!
julien_c
@julien_c, jeśli problem zostanie rozwiązany, oznacz go jako taki, aby umożliwić tym, którzy przyjadą po ciebie, skorzystanie z twojego doświadczenia tutaj.
mor7ifer,
Chcę tylko przetestować to w prawdziwym życiu, więc jestem pewien, że robi to, co chcę. Będę pamiętać, aby oznaczyć go jako rozwiązany, gdy tylko skończę!
julien_c,
3
Jeśli zobaczysz przydatne funkcje, których nie ma w kodeksie, warto je dodać (ta wiki) = p
Tom J Nowell
Przepraszam, że tyle czasu zajęło mi sprawdzenie, czy zadziałało w moim przypadku. Odpowiedź zaakceptowana! Ponadto definiujesz elementy menu niestandardowych linków , poniżej dodałem odpowiedź, aby zdefiniować linki do stron (na przykład bardziej odporne na zmiany adresów URL).
julien_c
12

Jako uzupełnienie anwsera ZaMoose, oto jak utworzysz pozycję menu „Typ strony ” (a nie „ niestandardową ”):

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'));

Zakładając, że znasz tylko ślimak strony.

julien_c
źródło
9

Mam kilka problemów z zaakceptowaną odpowiedzią - to nie jest źle, ale opublikuję własny kod, poniżej którego, moim zdaniem, może być lepszy wynik dla niektórych osób, ponieważ miałem to samo pytanie, ale chciałem zrobić to samo rzecz z mniejszym kodem.

Po pierwsze, powyższy kod tworzy elementy nawigacyjne typu „URL”, co jest w porządku dla niektórych osób, ale chcę link do STRON, a nie adresów URL, ponieważ jest to ważna funkcja nawigacji WordPress, a klienci nieuchronnie przenoszą rzeczy, więc nigdy nie używam adresu URL typ elementu nawigacyjnego.

Ponadto tylko wysłany kod obsługuje tylko płaską tablicę dzieci. Stworzyłem funkcję rekurencyjnego deklarowania nowych elementów nawigacyjnych, przechowywania ich zwróconych metadanych (głównie ID po utworzeniu w pętli) oraz parametr do akceptowania dzieci.

Po prostu edytuj, $nav_items_to_adda reszta jest obsługiwana rekurencyjnie. W każdej tablicy są 3 wymagane klucze. Po pierwsze, kluczem tablicy jest ślimak, więc 'shop' => array( ... )to, czego chcesz dla strony ze ślimakiem shop. ['title']to sposób, w jaki element nawigacyjny zostanie oznaczony na interfejsie. pathjest ścieżką do strony w hierarchii stron WordPress, więc jest to identyczne jak ślimak, jeśli strona jest rodzicem najwyższego poziomu, a jeśli byłaby shopdzieckiem home, byłaby 'path' => 'home/shop'.

Ostatni opcjonalny klucz tablicy to miejsce, w ['parent']którym możesz zadeklarować inny klucz w tablicy jako element nadrzędny bieżącego klucza. Ważne jest, aby pamiętać, że elementy są dodawane rekurencyjnie, więc rodzic musi istnieć przed próbą utworzenia dziecka. Oznacza to, że deklaracja powinna zostać wydana dla nadrzędnego elementu nawigacji, zanim będzie on podrzędny.

    $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')
        );
    }

    }
Brian
źródło
2

Aby dodać pozycję menu Programowo. możesz zaczepić, aby wp_nav_menu_itemsprzefiltrować. umieść poniżej kodu w funkcjach motywu. php, aby dodać pozycję menu logowania / wylogowania w menu głównym. „Podstawowy” to nazwa / identyfikator zarejestrowanego menu.

/**
 * 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;
}
Aamer Shahzad
źródło