wp_get_nav_menu_items() non funziona con lo slug

25 ago 2016, 01:53:32
Visualizzazioni: 17.3K
Voti: 11

Secondo la documentazione, il parametro 1 di wp_get_nav_menu_items() accetta

(string) (Obbligatorio) Nome del menu, ID o slug.

Ecco come registro i miei menu

register_nav_menus(
    array(
        'primary' => 'Navigazione principale',
        'secondary' => 'Navigazione secondaria',
    )
);

Ecco come ho provato a caricarne uno

var_dump( wp_get_nav_menu_items('primary') );             // bool(false)
var_dump( wp_get_nav_menu_items('navigazione-principale') ); // bool(false)
var_dump( wp_get_nav_menu_items('Navigazione principale') ); // bool(false)

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

Quindi, la funzione restituisce il menu solo quando uso l'ID. Preferirei usare lo slug poiché il mio sito è multilingua e non voglio dover usare ID diversi a seconda della lingua.

Sto facendo qualcosa di sbagliato o è un bug del core? Ho provato questo tema TwentySixteen con il mio plugin multilingua disabilitato (Polylang).

0
Tutte le risposte alla domanda 4
2
26

Dato che nessuno ha veramente spiegato perché la funzione non funziona nel modo in cui pensavi, cercherò di spiegarlo in dettaglio, dato che sono caduto nella stessa trappola.

Questo è il punto in cui la documentazione non è molto chiara su ciò a cui si riferisce lo "slug". La maggior parte delle persone presumerebbe che sia lo slug del menu registrato, ma non è corretto. In realtà, è lo slug del termine per la tassonomia nav_menu.

Analizziamo il codice sorgente per vedere come il core di WordPress interpreta lo slug del menu.

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

La prima riga mostra che utilizza una funzione chiamata wp_get_nav_menu_object() per recuperare il menu. Passa $menu come primo parametro a questa funzione. Poiché questo è ciò che usiamo per il nostro slug, dovremo analizzare il sorgente di 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' );
            }
    }
....

Possiamo vedere che questa funzione utilizza get_term_by per recuperare l'oggetto $menu_obj. Questo è da dove otteniamo il nostro menu.

Quando crei un menu nell'area amministrativa di WordPress, viene creato un nuovo termine. I termini hanno slug basati sul loro nome. Quindi, se hai un menu chiamato "Il Mio Fantastico Menu", WordPress genererà uno slug chiamato "il-mio-fantastico-menu". Potresti aver registrato il menu come "primary", ma non è questo lo slug a cui si riferiscono queste funzioni. È in realtà lo slug del termine del menu.

Per chiarire, supponiamo che tu abbia registrato un menu così:

register_nav_menu('primary', 'il mio menu principale');

primary non è lo slug. il-mio-menu-principale non è lo slug.

Poiché abbiamo creato un menu chiamato "Il Mio Fantastico Menu" (come esempio), e lo slug è 'il-mio-fantastico-menu', puoi recuperarlo così:

$awesome_menu = wp_get_nav_menu_items( 'il-mio-fantastico-menu' );

Puoi verificare tu stesso quale sia lo slug controllando il database nella tabella wp_terms (o qualsiasi sia il tuo prefisso) e cercare il nome del tuo menu lì.

Dato che stai utilizzando un sito multilingue o addirittura un multisite, questo metodo non sarà il migliore. Poiché il nome e lo slug potrebbero essere diversi.

Quindi il metodo migliore è ottenere tutte le posizioni dei menu con get_nav_menu_locations(), che restituirà un array associativo in cui la chiave è lo slug del menu registrato e il valore è l'id del termine del menu selezionato per quella posizione.

Con l'id del termine, possiamo ottenere le informazioni di quel termine e quindi restituire lo slug corretto richiesto dalla funzione.

Di seguito è riportata una funzione che utilizza wp_get_nav_items() ma a cui passerai lo slug del menu registrato. Nel tuo caso sarebbe 'primary'.

Soluzione Codice

// un nome di funzione piuttosto lungo, ma va bene lo stesso
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 giu 2017 03:09:05
Commenti

Spiegazione eccellente.

Bagseye Bagseye
26 nov 2021 12:23:01

Così ben spiegato, a differenza della documentazione (proverò ad aggiungerlo nei commenti). Ho perso ore su questo pensando fosse un problema di timing degli hook.. GRAZIE.

cdsaenz cdsaenz
24 nov 2023 01:34:16
0

Piccola modifica alla risposta accettata

Dopo aver rimosso un menu dalla posizione dei menu, $locations[ $menu_slug ] restituisce 0, quindi è bene aggiungere questo controllo:

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

Prova questo:

    $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);
        // Il tuo codice di output
    }
25 ago 2016 13:06:21
Commenti

Potresti spiegare un po' perché la tua risposta funzionerebbe?

cjbj cjbj
25 ago 2016 13:36:42

Non sembra funzionare per me. get_nav_menu_locations() restituisce un array con un singolo elemento ('primary' => 51), ma wp_get_nav_menu_items() restituisce false quando si utilizza uno slug.

somebodysomewhere somebodysomewhere
25 ago 2016 17:54:07

Ho appena realizzato che posso usare l'array da get_nav_menu_locations() per caricare il menu corretto per lingua senza bisogno di definire costanti. Grazie per avermi fatto conoscere questa funzione.

somebodysomewhere somebodysomewhere
25 ago 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);
    //il tuo codice per il menu.
}
19 mag 2017 09:51:59