wp_get_nav_menu_items() nu funcționează cu slug-ul

25 aug. 2016, 01:53:32
Vizualizări: 17.3K
Voturi: 11

Conform documentației, primul parametru al funcției wp_get_nav_menu_items() acceptă:

(string) (Obligatoriu) Numele meniului, ID-ul sau slug-ul.

Iată cum îmi înregistrez meniurile:

register_nav_menus(
    array(
        'primary' => 'Navigation primaire',
        'secondary' => 'Navigation secondaire',
    )
);

Iată cum am încercat să încărc un meniu:

var_dump( wp_get_nav_menu_items('primary') );             // bool(false)
var_dump( wp_get_nav_menu_items('navigation-primaire') ); // bool(false)
var_dump( wp_get_nav_menu_items('Navigation primaire') ); // bool(false)

var_dump( wp_get_nav_menu_items(51) );                    // array([...]) (corect)

Funcția returnează meniul doar când folosesc ID-ul. Aș prefera să folosesc slug-ul, deoarece site-ul meu este multilingv și nu vreau să fiu nevoit să folosesc ID-uri diferite în funcție de limbă.

Fac ceva greșit sau este aceasta o problemă din nucleul WordPress? Am încercat acest lucru pe tema TwentySixteen cu plugin-ul meu multilingv dezactivat (Polylang).

0
Toate răspunsurile la întrebare 4
2
26

Deoarece nimeni nu a explicat cu adevărat de ce funcția nu funcționează așa cum te așteptai, voi încerca să explic în detaliu, deoarece am căzut și eu în aceeași capcană.

Problema este că documentația nu este foarte clară în legătură cu ce se referă slug-ul. Majoritatea oamenilor ar presupune că este slug-ul meniului înregistrat, dar acest lucru nu este corect. De fapt, este slug-ul termenului pentru taxonomia nav_menu.

Să analizăm codul sursă pentru a vedea cum interpretează nucleul WordPress slug-ul meniului.

function wp_get_nav_menu_items( $menu, $args = array() ) {
    $menu = wp_get_nav_menu_object( $menu );
....

Prima linie arată că utilizează o funcție numită wp_get_nav_menu_object() pentru a prelua meniul. Aceasta trece $menu ca prim parametru. Deoarece acesta este slug-ul pe care îl folosim, va trebui să analizăm sursa pentru wp_get_nav_menu_object().

function wp_get_nav_menu_object( $menu ) {
    $menu_obj = false;

    if ( is_object( $menu ) ) {
            $menu_obj = $menu;
    }

    if ( $menu && ! $menu_obj ) {
            $menu_obj = get_term( $menu, 'nav_menu' );

            if ( ! $menu_obj ) {
                    $menu_obj = get_term_by( 'slug', $menu, 'nav_menu' );
            }

            if ( ! $menu_obj ) {
                    $menu_obj = get_term_by( 'name', $menu, 'nav_menu' );
            }
    }
....

Putem vedea că această funcție utilizează get_term_by pentru a prelua $menu_obj. Aici obținem meniul nostru.

Când creezi un meniu în zona de administrare WordPress, acesta creează un nou termen. Termenii au slug-uri bazate pe numele lor. De exemplu, dacă ai un meniu numit "Meniuul Meu Minunat", WordPress va genera un slug numit "meniul-meu-minunat". Poate că ai înregistrat meniul ca "primary", dar acesta nu este slug-ul la care se referă aceste funcții. De fapt, este slug-ul termenului meniului.

Pentru a fi clar, să presupunem că ai înregistrat un meniu astfel:

register_nav_menu('primary', 'Navigația mea principală');

primary nu este slug-ul. navigatia-mea-principala nu este nici el slug-ul.

Deoarece am creat un meniu numit "Meniuul Meu Minunat" (ca exemplu), iar slug-ul este 'meniul-meu-minunat', îl poți prelua astfel:

$awesome_menu = wp_get_nav_menu_items( 'meniul-meu-minunat' );

Poți verifica singur care este slug-ul verificând în baza de date tabela wp_terms (sau orice prefix ai) și căutând numele meniului acolo.

Dacă folosești un site multilingv sau chiar un multisite, această metodă nu va fi cea mai bună, deoarece numele și slug-ul ar putea fi diferite.

Deci, cea mai bună metodă este să obții toate locațiile meniurilor cu get_nav_menu_locations(), care va returna un array asociativ în care cheia este slug-ul meniului înregistrat, iar valoarea este ID-ul termenului meniului selectat pentru acea locație.

Cu ID-ul termenului, putem obține informațiile despre acel termen și apoi returna slug-ul corect pe care îl cere funcția.

Mai jos este o funcție care utilizează wp_get_nav_items(), dar ai putea pasa slug-ul meniului înregistrat. În cazul tău, acesta ar fi 'primary'.

Soluția de Cod

// un nume destul de lung pentru funcție, dar asta e
function get_menu_items_by_registered_slug($menu_slug) {

    $menu_items = array();

    if ( ( $locations = get_nav_menu_locations() ) && isset( $locations[ $menu_slug ] ) ) {
        $menu = get_term( $locations[ $menu_slug ] );

        $menu_items = wp_get_nav_menu_items($menu->term_id);


    }

    return $menu_items;

}
2 iun. 2017 03:09:05
Comentarii

Explicație excelentă.

Bagseye Bagseye
26 nov. 2021 12:23:01

Atât de bine explicat, spre deosebire de documentație (voi încerca să adaug asta în comentarii). Am pierdut ore întregi cu asta crezând că e vorba de momentul hook-ului.. MULȚUMESC.

cdsaenz cdsaenz
24 nov. 2023 01:34:16
0

Mică modificare la răspunsul acceptat

După eliminarea unui meniu din locația meniului, $locations[ $menu_slug ] returnează 0, deci este bine să adăugați această verificare:

function get_menu_items_by_registered_slug($menu_slug) {
  $menu_items = array();

  if ( ($locations = get_nav_menu_locations()) && isset($locations[$menu_slug]) && $locations[$menu_slug] != 0 ) {
    $menu = get_term( $locations[ $menu_slug ] );
    $menu_items = wp_get_nav_menu_items($menu->term_id);
  }

  return $menu_items;
}
27 apr. 2018 13:38:11
3

Încearcă asta:

    $menu_name = 'primary'; 

    if ( ( $locations = get_nav_menu_locations() ) && isset( $locations[ $menu_name ] ) ) {
        $menu = wp_get_nav_menu_object( $locations[ $menu_name ] );

        $menu_items = wp_get_nav_menu_items($menu->term_id);
        // Codul tău de afișare
    }
25 aug. 2016 13:06:21
Comentarii

Poți explica puțin de ce răspunsul tău ar funcționa?

cjbj cjbj
25 aug. 2016 13:36:42

Nu pare să funcționeze pentru mine. get_nav_menu_locations() returnează un array cu un singur element ('primary' => 51), dar wp_get_nav_menu_items() returnează false când folosești un slug.

somebodysomewhere somebodysomewhere
25 aug. 2016 17:54:07

Tocmai am realizat că pot folosi array-ul din get_nav_menu_locations() pentru a încărca meniul corect pe limbă fără a fi nevoie să definesc constante. Mulțumesc că m-ai făcut conștient de această funcție.

somebodysomewhere somebodysomewhere
25 aug. 2016 18:09:51
0
custom_menu('primary');

function custom_menu( $theme_location ) {
if ( ($theme_location) && ($locations = get_nav_menu_locations()) && isset($locations[$theme_location]) ) {
    $menu = get_term( $locations[$theme_location], 'nav_menu' );
    $menu_items = wp_get_nav_menu_items($menu->term_id);
    //codul tău pentru meniu.
}
19 mai 2017 09:51:59