Eroare "Trying to get property of non-object" cu Walker personalizat pentru wp_nav_menu

16 iun. 2013, 16:07:29
Vizualizări: 18.5K
Voturi: 10

Încerc să adaug elemente ARIA la funcția wp_nav_menu. Folosesc o clasă Walker personalizată pentru asta:

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 ) . '"' : '';

                // Adaugă atribute pentru <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        ) .'"' : '';

                // Adaugă atribute pentru <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";
        }
}

Am copiat pur și simplu clasa originală Walker_Nav_Menu și am adăugat elemente, dar primesc erori pentru că variabila $args este tratată ca obiect când de fapt este un array. Lucrul ciudat este că această eroare persistă chiar dacă folosesc Walker-ul original astfel:

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

Acestea sunt mesajele de eroare pe care le primesc:

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

Liniile arată astfel (în fișierul original!):

(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;
8
Comentarii

Primești eroare dacă nu transmiți deloc walker? Argumentele ar trebui să fie obiect, cred că asta spun documentațiile inline și asta transmite wp_nav_menu().

Rarst Rarst
16 iun. 2013 18:02:38

Nu, dacă folosesc funcția implicită wp_nav_menu() fără un walker, funcționează perfect. Da, dar atunci de ce este un array? Am făcut chiar var_dump, nu e obiect.

Rudolf Rudolf
16 iun. 2013 18:26:16

Nu sunt sigur ce se întâmplă atunci, pentru că transmiterea new Walker_Nav_Menu ar trebui să se comporte identic cu absența walker-ului. Se întâmplă altceva, există plugin-uri care intervin / manipulează funcționalitatea meniului?

Rarst Rarst
16 iun. 2013 18:27:39

Tocmai am făcut niște teste suplimentare și sunt sigur că aceasta este o eroare în WordPress. În cazul meu, meniul de navigare pe care l-am folosit nu era atribuit în administrare. Prin urmare, s-a folosit varianta implicită cu lista de pagini, iar se pare că în acest caz variabila args este un array. Voi urmări acum această problemă până la sursă, apoi vă voi spune ce am descoperit.

Rudolf Rudolf
16 iun. 2013 18:40:24

Dacă atribui corect un meniu, funcționează!

Rudolf Rudolf
16 iun. 2013 18:40:42

La început nu am văzut răspunsul de mai jos, uitați-vă acolo pentru soluție.

Rudolf Rudolf
16 iun. 2013 18:59:11

Am încercat if(wp_nav_menu()) și codul funcționează.

User User
1 sept. 2015 09:59:09

Îți dai seama că această întrebare are doi ani? :D Dar am creat un tichet pentru ea aici: https://core.trac.wordpress.org/ticket/24587 Încă nu este rezolvată, așa că simte-te liber să discuți despre ea acolo!

Rudolf Rudolf
1 sept. 2015 17:15:05
Arată celelalte 3 comentarii
Toate răspunsurile la întrebare 2
5
21

Primesc această eroare atunci când nu sunt definite meniuri sau nu sunt setate meniuri pentru locația în Apariție->Meniuri. Când se întâmplă asta, wp_nav_menu folosește un fallback de tip page walker.

  1. Fallback-ul (implicit) pentru wp_nav_menu este wp_walker_page
  2. care folosește wp_page_menu
  3. care folosește wp_list_pages
  4. care folosește walk_page_tree
  5. care folosește Walker_Page, nu Walker_Nav_Menu.

Și aparent, cei doi walkeri nu sunt compatibili. Nu știu de ce nu eșuează elegant. Asta mi se pare a fi un bug.

Cu un meniu setat în wp-admin->Apariție->Meniuri, codul tău funcționează.

Poți evita eroarea verificând dacă există un meniu asignat locației înainte de a încerca să folosești locația.

$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,
  ) );
}

Sau, dacă preferi un cod mai puțin "antihistaminic" (mulțumesc @Rarst):

if (has_nav_menu('primary')) {
  wp_nav_menu( array(
      'theme_location' => 'primary',
      'walker'         => new Walker_Nav_Menu_With_Aria,
  ) );
}
16 iun. 2013 17:05:02
Comentarii

Fallback-ul este folosit doar atunci când toate celelalte metode eșuează în afișarea paginilor. Dacă meniul funcționează corect, elementele sunt parcurse cu walk_nav_menu_tree(), care utilizează implicit Walker_Nav_Menu.

Rarst Rarst
16 iun. 2013 17:57:40

Actualizare frumoasă! Nu mi-a trecut prin cap că o funcție greșită ar putea prelua walker-ul (asta e cam meh). De asemenea, există has_nav_menu() pentru această verificare.

Rarst Rarst
16 iun. 2013 18:34:35

Exact asta voiam să postez și eu :D Argumentele $args ale meniului de navigare sunt convertite într-un obiect în wp-includes/nav-menu-template.php la linia 145 de către funcția wp_nav_menu(). Funcția wp_page_menu(), care este folosită ca fallback, nu face asta, ci doar transmite array-ul către Walker-ul din meniul de navigare care are nevoie de obiect.

Dacă adaugi un $args = (object) $args la începutul funcției start_el din clasa Walker, poți rezolva această problemă. Unde ar fi locul potrivit pentru a raporta această problemă echipei WordPress?

Rudolf Rudolf
16 iun. 2013 18:57:34

@Rudolf problemele de bază ar trebui raportate pe http://core.trac.wordpress.org/

Rarst Rarst
16 iun. 2013 19:00:40

Obiectul WP_Post care este transmis ca $item este diferit, de asemenea (Din această cauză, paginile nu au nume și lista constă doar din elemente goale <li>). Ar fi necesară o refactorizare serioasă pentru a face acești doi walkeri compatibili.

Rudolf Rudolf
16 iun. 2013 19:04:43
0

folosește codul de mai jos pentru reparare:

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;
}
21 aug. 2017 03:37:06