Erreur "Essayer d'obtenir la propriété d'un non-objet" avec Walker personnalisé pour wp_nav_menu

8

J'essaie d'ajouter des éléments liés à ARIA à la fonction wp_nav_menu. J'utilise une classe de marcheur personnalisée à cet effet:

class Walker_Nav_Menu_With_Aria extends Walker_Nav_Menu {
        function start_lvl( &$output, $depth = 0, $args = array() ) {
                $indent = str_repeat("\t", $depth);
                $output .= "\n$indent<ul class=\"sub-menu\" role=\"group\">\n";
        }

        function end_lvl( &$output, $depth = 0, $args = array() ) {
                $indent = str_repeat("\t", $depth);
                $output .= "$indent</ul>\n";
        }

        function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
                $indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';

                $class_names = $value = '';

                $classes = empty( $item->classes ) ? array() : (array) $item->classes;
                $classes[] = 'menu-item-' . $item->ID;

                $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
                $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';

                $id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
                $id = $id ? ' id="' . esc_attr( $id ) . '"' : '';

                // Add attributes for <li>
                $li_attributes  = ' role="treeitem"';
                $li_attributes .= ' aria-expanded="false"';

                $output .= $indent . '<li' . $id . $value . $class_names . $li_attributes .'>';

                $attributes  = ! empty( $item->attr_title ) ? ' title="'  . esc_attr( $item->attr_title ) .'"' : '';
                $attributes .= ! empty( $item->target )     ? ' target="' . esc_attr( $item->target     ) .'"' : '';
                $attributes .= ! empty( $item->xfn )        ? ' rel="'    . esc_attr( $item->xfn        ) .'"' : '';
                $attributes .= ! empty( $item->url )        ? ' href="'   . esc_attr( $item->url        ) .'"' : '';

                // Add attributes for <a>
                $attributes .= $depth == 0 ? ' tabindex="0"' : ' tabindex="-1"';

                $item_output = $args->before;
                $item_output .= '<a'. $attributes .'>';
                $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
                $item_output .= '</a>';
                $item_output .= $args->after;

                $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
        }

        function end_el( &$output, $item, $depth = 0, $args = array() ) {
                $output .= "</li>\n";
        }
}

Je viens de copier-coller la classe Walker_Nav_Menu originale et d'ajouter des trucs, mais je reçois des erreurs car la variable $ args traitée comme un objet est vraiment un tableau. Mais la chose vraiment bizarre est que cette erreur persiste, même si je passe dans le déambulateur d'origine comme ceci:

wp_nav_menu( array(
    'theme_location' => 'main-nav',
    'walker'         => new Walker_Nav_Menu,
) );

Voici les messages d'erreur que j'obtiens:

NOTICE: TRYING TO GET PROPERTY OF NON-OBJECT IN /USERS/RUDOLF/SITES/LOCALHOST/WP/WP-INCLUDES/NAV-MENU-TEMPLATE.PHP ON LINE 88
NOTICE: TRYING TO GET PROPERTY OF NON-OBJECT IN /USERS/RUDOLF/SITES/LOCALHOST/WP/WP-INCLUDES/NAV-MENU-TEMPLATE.PHP ON LINE 90
NOTICE: TRYING TO GET PROPERTY OF NON-OBJECT IN /USERS/RUDOLF/SITES/LOCALHOST/WP/WP-INCLUDES/NAV-MENU-TEMPLATE.PHP ON LINE 90
NOTICE: TRYING TO GET PROPERTY OF NON-OBJECT IN /USERS/RUDOLF/SITES/LOCALHOST/WP/WP-INCLUDES/NAV-MENU-TEMPLATE.PHP ON LINE 92

Les lignes ressemblent à ceci (dans le fichier d'origine!):

(88) $item_output = $args->before;
(89) $item_output .= '<a'. $attributes .'>';
(90) $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
(91) $item_output .= '</a>';
(92) $item_output .= $args->after;
Rudolf
la source
Avez-vous une erreur si vous ne passez pas du tout à pied? Les arguments doivent être objectifs, je pense que c'est ce que disent les documents en ligne et ce qui wp_nav_menu()passe.
Rarst
Non, si j'utilise simplement la wp_nav_menu()fonction par défaut sans déambulateur, cela fonctionne parfaitement. Oui, mais pourquoi est-ce un tableau alors? Je l'ai même var_dumpédité, sans objet.
Rudolf
Je ne sais pas trop ce qui se passe alors, car les passes new Walker_Nav_Menudoivent se comporter de la même manière que les marcheurs qui ne passent pas. Y a-t-il autre chose qui se passe, des plugins se connectant / manipulant la fonctionnalité du menu?
Rarst
Je viens de faire des tests supplémentaires, et je suis sûr que c'est un bug WordPress. Dans mon cas, le menu de navigation que j'ai utilisé n'a pas été attribué dans le backend. Par conséquent, le remplacement des pages de liste a été utilisé, il semble que la variable args soit alors un tableau. Je vais remonter à la source maintenant, puis vous dire ce que j'ai trouvé.
Rudolf
Si j'attribue correctement un menu, cela fonctionne!
Rudolf

Réponses:

18

J'obtiens cette erreur lorsqu'il n'y a aucun menu défini ou aucun menu défini pour l'emplacement à Appearance->Menus. Lorsque cela se produit, wp_nav_menuutilise une solution de rechange pour le marcheur de page.

  1. Le repli (par défaut) pourwp_nav_menu estwp_walker_page
  2. qui utilise wp_page_menu
  3. qui utilise wp_list_pages
  4. qui utilise walk_page_tree
  5. qui n'utilise Walker_Pagepas Walker_Nav_Menu.

Et apparemment, les deux marcheurs ne sont pas compatibles. Je ne sais pas pourquoi cela n'échoue pas gracieusement. Cela me semble être un bug.

Avec un menu défini sur wp-admin->Appearance->Menus, votre code fonctionne.

Vous pouvez éviter l'erreur en vérifiant qu'un menu est affecté à l'emplacement avant d'essayer d'utiliser l'emplacement.

$locations = get_nav_menu_locations();
if (0 !== $locations['main-nav']) {
  wp_nav_menu( array(
      'theme_location' => 'main-nav',
      'walker'         => new Walker_Nav_Menu_With_Aria,
  ) );
}

Ou, si vous préférez moins de code additionné d'antihistaminiques (merci @Rarst):

if (has_nav_menu('primary')) {
  wp_nav_menu( array(
      'theme_location' => 'primary',
      'walker'         => new Walker_Nav_Menu_With_Aria,
  ) );
}
s_ha_dum
la source
Le remplacement n'est utilisé que lorsque tout le reste ne parvient pas à afficher les pages. Si le menu fonctionne correctement, les éléments sont parcourus avec ceux walk_nav_menu_tree()qui sont utilisés Walker_Nav_Menupar défaut.
Rarst
Belle mise à jour! Je ne me suis pas rendu compte qu'une fonction incorrecte pouvait être de saisir le déambulateur (c'est meh). Il y a aussi has_nav_menu()pour ce chèque.
Rarst
C'est exactement ce que je voulais simplement publier: D Le menu nav $argsest converti en un objet en wp-includes/nav-menu-template.phpligne 145 par la wp_nav_menu()fonction. La wp_page_menu()fonction utilisée comme solution de repli ne fait pas cela, mais passe simplement le tableau au Walker à partir du menu nav qui a besoin de l'objet. Si vous ajoutez juste un $args = (object) $argsen haut de la start_elfonction de la classe Walker, vous pouvez résoudre ce problème. Où serait le bon endroit pour signaler cela à l'équipe WordPress?
Rudolf
Les bogues de base @Rudolf doivent être signalés sur core.trac.wordpress.org
Rarst
L' WP_Postobjet transmis en tant que tel $itemest également différent (à cause de cela, les pages n'ont pas de noms et la liste se compose uniquement d' <li>éléments vides ). Une refonte sérieuse serait nécessaire pour rendre ces deux marcheurs compatibles.
Rudolf
0

utilisez le code ci-dessous pour réparer:

add_filter( 'wp_get_nav_menu_object', 'override_wp_get_nav_menu_object', 10, 2 );
function override_wp_get_nav_menu_object( $menu_obj, $menu ) {

    if ( ! is_object( $menu_obj ) ) {
        $menu_obj = (object) array( 'name' => '' );
    }

    return $menu_obj;
}
hannanstd
la source