web-dev-qa-db-fra.com

wp_get_nav_menu_items () ne fonctionne pas avec slug

Selon le docs , wp_get_nav_menu_items(), le paramètre 1 accepte

(string) (Required) Menu name, ID, or slug.

Voici comment enregistrer mes menus

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

Voici comment j'ai essayé d'en charger un

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([...]) (correct)

La fonction ne renvoie donc le menu que lorsque j'utilise l'ID. Je préférerais de loin utiliser le slug car mon site est multilingue et je ne souhaite pas avoir à utiliser différents identifiants en fonction de la langue.

Est-ce que je fais quelque chose de mal ou est-ce un bug principal? J'ai essayé ceci sur le thème TwentySixteen avec mon plugin multilingue désactivé (Polylang).

6
Brian

Puisque personne n'a vraiment expliqué pourquoi la fonction ne fonctionnait pas comme vous le pensiez, je vais essayer de l'expliquer en détail car je suis tombé dans le même piège.

C'est là que les documents ne sont pas vraiment clairs quant à la référence du slug. La plupart des gens penseraient que c'est la note du menu inscrit, mais ce n'est pas correct C'est en fait le slug du terme pour la taxonomie nav_menu.

Permet de plonger dans le code source pour voir comment le noyau Wordpress interprète le slug du menu.

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

La première ligne montre qu'il utilise une fonction nommée wp_get_nav_menu_object () pour récupérer le menu. Il passe le $menu en tant que premier paramètre à cette fonction. Puisque c'est ce que nous utilisons pour notre slug, nous devrons plonger dans la source pour 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' );
            }
    }
....

nous pouvons voir que cette fonction utilise la fonction get_term_by pour récupérer le $menu_obj. C'est là que nous obtenons notre menu.

Lorsque vous créez un menu dans la zone d'administration Wordpress, un nouveau terme est créé. Termes, ont des slugs basés sur leur nom. Donc, si vous avez le nom de menu "Mon menu génial", Wordpress générera un slug nommé "mon menu génial". Vous avez peut-être enregistré le menu comme "primaire", mais ce n’est pas le slug auquel ces fonctions se réfèrent. C'est en fait les menus terme limace.

Donc, pour être clair, disons simplement que vous avez enregistré un menu comme suit:

register_nav_menu('primary', 'my primary nav');

primary n'est pas la limace. my-primary-nav n'est pas non plus la limace.

Depuis que nous avons créé un menu nommé "My Awesome Menu" (à titre d'exemple), et que le slug est "my-awesome-menu", vous pouvez le récupérer comme suit:

$awesome_menu = wp_get_nav_menu_items( 'my-awesome-menu' );

Vous pouvez voir par vous-même ce qu'est le slug simplement en consultant la base de données dans la table wp_terms (ou quel que soit votre préfixe) et en y cherchant le nom de votre menu.

Puisque vous utilisez un site multilingue ou même un multisite, cette méthode ne sera pas la meilleure façon de s'y prendre. Puisque le nom et la limace pourraient éventuellement être différents.

La meilleure méthode consiste donc à obtenir tous les emplacements de menu avec get_nav_menu_locations(), ce qui renverra un tableau associatif où la clé est le slug du menu enregistré et la valeur est l'id du terme de menu sélectionné pour son emplacement.

Avec le terme id, nous pouvons obtenir ces informations sur les termes, puis renvoyer le slug approprié requis par la fonction.

Vous trouverez ci-dessous une fonction qui utilise la fonction wp_get_nav_items() mais vous transmettriez le slug de menu enregistré. Dans votre cas, ce serait "primaire".

Solution de code

// kind of a long function name but whatevs
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;

}
12
JoeMoe1984

Petite modification de la réponse acceptée

Après avoir supprimé un menu de l'emplacement du menu, $locations[ $menu_slug ] renvoie 0, il est donc bon d'ajouter cette vérification:

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;
}
1
Narek

Essaye ça:

    $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);
        // Your output code
    }
0
Ignat B.
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);
    //your menu code.
}
0