Adăugarea programatică a unui meniu de navigare și a elementelor de meniu

7 mar. 2012, 15:43:00
Vizualizări: 58.2K
Voturi: 51

Prin intermediul funcțiilor API, doresc să definesc un nou meniu de navigare, să îl selectez în tema curentă și apoi să inserez câteva Pagini ca elemente de meniu. Acest lucru trebuie făcut, de exemplu, la activarea unei teme.

Printr-un proces (moderat dificil) de inginerie inversă a inserărilor și actualizărilor din baza de date după configurarea manuală a meniului de navigare și a elementelor, am asamblat următorii pași, unde 'footer-nav' este ID-ul slug al meniului de navigare pe care îl creez:

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

    // Inserează noul meniu
    $menu = wp_insert_term('Footer nav', 'nav_menu', array('slug' => 'footer-nav'));

    // Selectează acest meniu în tema curentă
    update_option('theme_mods_'.get_current_theme(), array("nav_menu_locations" => array("primary" => $menu['term_id'])));

    // Inserează pagină nouă
    $page = wp_insert_post(array('post_title' => 'Blog',
                                 'post_content' => '',
                                 'post_status' => 'publish',
                                 'post_type' => 'page'));

    // Inserează element nou nav_menu_item
    $nav_item = wp_insert_post(array('post_title' => 'Știri',
                                     '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');
}

Acest lucru pare să funcționeze, dar:

  • este o modalitate robustă și elegantă de a face acest lucru?
  • îmi scapă ceva total evident care ar face toate acestea într-o singură linie de cod?
0
Toate răspunsurile la întrebare 4
7
53

S-ar putea să te înțeleg greșit, dar de ce să nu folosești wp_create_nav_menu()?

De exemplu, iată ce fac pentru a crea un meniu personalizat BuddyPress atunci când detectez BP ca fiind activ:

    $menuname = $lblg_themename . ' BuddyPress Menu';
$bpmenulocation = 'lblgbpmenu';
// Există deja meniul?
$menu_exists = wp_get_nav_menu_object( $menuname );

// Dacă nu există, îl creăm.
if( !$menu_exists){
    $menu_id = wp_create_nav_menu($menuname);

    // Configurăm link-urile implicite pentru BuddyPress și le adăugăm în meniu.
    wp_update_nav_menu_item($menu_id, 0, array(
        'menu-item-title' =>  __('Acasă'),
        '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' =>  __('Activitate'),
        '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' =>  __('Membri'),
        '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' =>  __('Grupuri'),
        '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' =>  __('Forumuri'),
        'menu-item-classes' => 'forums',
        'menu-item-url' => home_url( '/forums/' ), 
        'menu-item-status' => 'publish'));

    // Preluăm locațiile temei și atribuim noul meniu creat
    // la locația meniului BuddyPress.
    if( !has_nav_menu( $bpmenulocation ) ){
        $locations = get_theme_mod('nav_menu_locations');
        $locations[$bpmenulocation] = $menu_id;
        set_theme_mod( 'nav_menu_locations', $locations );
    }
7 mar. 2012 16:03:26
Comentarii

Nu știam despre această funcție. Da, presupun că va face codul de mai sus mult mai scurt. Cred că ar trebui să depășesc Codex-ul și să aprofundez codul real, deoarece observ că funcțiile API sunt adesea, ca în acest caz, prea de nivel scăzut. Mulțumesc!

julien_c julien_c
7 mar. 2012 16:18:16

@julien_c dacă această problemă este rezolvată, marcheaz-o ca atunci pentru a permite celor care vin după tine să beneficieze de experiența ta de aici.

mor7ifer mor7ifer
7 mar. 2012 17:07:59

Vreau doar să o testez în practică pentru a mă asigura că face exact ceea ce doresc. Îmi voi aminti să o marchez ca rezolvată imediat ce termin!

julien_c julien_c
7 mar. 2012 17:51:33

Dacă găsești funcții utile ca acestea care nu sunt în codex, e o idee bună să le adaugi (ura wiki) =p

Tom J Nowell Tom J Nowell
9 mar. 2012 21:51:56

Îmi pare rău că mi-a luat atât de mult timp să verific că funcționează în cazul meu. Răspuns acceptat! De asemenea, tu definești elemente de meniu cu link-uri personalizate, eu am adăugat un răspuns mai jos pentru a defini link-uri către pagini (care vor fi mai robuste la schimbări de URL, de exemplu).

julien_c julien_c
15 mai 2012 14:06:01

Cum poți crea subpagini folosind această abordare?

Joren Joren
28 dec. 2013 16:47:48
Arată celelalte 2 comentarii
1
17

Am câteva probleme cu răspunsul acceptat - asta nu înseamnă că este greșit, dar voi posta mai jos propriul meu cod care cred că ar putea avea un rezultat mai bun pentru unii utilizatori, având în vedere că am avut aceeași întrebare dar am vrut să fac același lucru cu mai puțin cod.

În primul rând, codul de mai sus creează elemente de navigare de tip "URL", ceea ce este ok pentru unii, dar eu vreau să leg la PAGINI, nu la URL-uri deoarece aceasta este o caracteristică importantă a navigațiilor WordPress și clienții mută inevitabil lucrurile, așa că nu folosesc niciodată tipul de element de navigare URL.

De asemenea, codul postat gestionează doar un array plat de copii. Am creat o funcție pentru declararea recursivă a noilor elemente de navigare, stocând metadatele returnate (în principal ID-ul după creare în buclă) și un parametru pentru acceptarea copiilor.

Doar editați $nav_items_to_add iar restul este gestionat recursiv. Există 3 chei obligatorii în fiecare array. În primul rând, cheia array-ului este slug-ul, deci 'shop' => array( ... ) este ceea ce doriți pentru o pagină cu slug-ul shop. ['title'] este modul în care elementul de navigare va fi etichetat în front-end. path este calea către pagina în ierarhia WordPress, deci este identic cu slug-ul dacă pagina este părinte de nivel superior, iar dacă shop ar fi copil al home, atunci ar fi 'path' => 'home/shop'.

Ultima cheie opțională a array-ului este ['parent'] unde puteți declara o altă cheie din array ca părinte al celei curente. Este important de reținut că elementele sunt adăugate recursiv, așa că părintele trebuie să existe înainte de a încerca să creați un copil. Aceasta înseamnă că declarația trebuie să se întâmple pentru elementul de navigare părinte înaintea copiilor săi.

    $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' => 'Magazin',
                    'path' => 'shop',
                    ),
                'shop_l2' => array(
                    'title' => 'Magazin',
                    'path' => 'shop',
                    'parent' => 'shop',
                    ),
                'cart' => array(
                    'title' => 'Coș',
                    'path' => 'shop/cart',
                    'parent' => 'shop',
                    ),
                'checkout' => array(
                    'title' => 'Finalizare comandă',
                    'path' => 'shop/checkout',
                    'parent' => 'shop',
                    ),
                'my-account' => array(
                    'title' => 'Contul meu',
                    'path' => 'shop/my-account',
                    'parent' => 'shop',
                    ),
                'lost-password' => array(
                    'title' => 'Parolă pierdută',
                    'path' => 'shop/my-account/lost-password',
                    'parent' => 'my-account',
                    ),
                'edit-address' => array(
                    'title' => 'Editează adresa',
                    '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 mai 2013 02:04:18
Comentarii

Aceasta este o soluție foarte inteligentă. Mulțumesc pentru adăugare. Exact ce aveam nevoie.

Juergen Schulze Juergen Schulze
2 iun. 2020 12:47:23
0
14

Ca un complement la răspunsul lui ZaMoose, iată cum ai putea crea un element de meniu de tip "Pagină" (nu unul "Personalizat"):

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

Presupunând că cunoști doar slug-ul paginii, de exemplu.

15 mai 2012 14:04:09
0

Pentru a adăuga un element de meniu programatic, poți folosi filtrul wp_nav_menu_items. Pune codul de mai jos în fișierul functions.php al temei tale pentru a adăuga un element de autentificare/deconectare în meniul principal. 'Primary' este numele/ID-ul meniului înregistrat.

/**
 * Adaugă un element de autentificare/deconectare în meniul principal.
 * ===========================================
 */

add_filter( 'wp_nav_menu_items', 'lunchbox_add_loginout_link', 10, 2 );
function lunchbox_add_loginout_link( $items, $args ) {
    /**
     * Dacă meniul principal este setat și utilizatorul este autentificat.
     */
    if ( is_user_logged_in() && $args->theme_location == 'primary' ) {
        $items .= '<li><a href="'. wp_logout_url() .'">Deconectare</a></li>';
    }
    /**
     * Altfel, afișează elementul de autentificare.
     */
    elseif ( !is_user_logged_in() && $args->theme_location == 'primary' ) {
        $items .= '<li><a href="'. site_url('wp-login.php') .'">Autentificare</a></li>';
    }
    return $items;
}
8 mar. 2016 20:49:56