Errore "Tentativo di ottenere proprietà di non oggetto" con Custom Walker per wp_nav_menu


8

Sto cercando di aggiungere alcune cose relative ad ARIA alla funzione wp_nav_menu. Uso una classe walker personalizzata per questo scopo:

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";
        }
}

Ho appena copiato e incollato la classe Walker_Nav_Menu originale e aggiunto elementi, ma sto ricevendo errori perché la variabile $ args trattata come un oggetto è davvero un array. Ma la cosa davvero strana è che questo errore persiste, anche se passo il walker originale in questo modo:

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

Questi sono i messaggi di errore che ottengo:

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

Le linee sono così (Nel file originale!):

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

Viene visualizzato un errore se non si passa affatto a Walker? Gli argomenti dovrebbero essere oggetto, penso che sia quello che dicono i documenti in linea e ciò che wp_nav_menu()passa.
Rarst

No, se uso semplicemente la wp_nav_menu()funzione predefinita senza un deambulatore, funziona perfettamente. Sì, ma allora perché è un array? L'ho persino var_dumpfatto, nessun oggetto.
Rudolf,

Non sono sicuro di cosa stia succedendo allora, perché il passaggio new Walker_Nav_Menudovrebbe comportarsi in modo identico al non passare il camminatore. Sta succedendo qualcos'altro, qualche plugin che si aggancia / manipola la funzionalità del menu?
Rarst

Ho appena fatto alcuni test aggiuntivi e sono sicuro che si tratta di un bug di WordPress. Nel mio caso, il menu di navigazione che ho usato non è stato assegnato nel backend. Pertanto è stato utilizzato il fallback delle pagine dell'elenco, sembra che quindi la variabile args sia un array. Traccerò questo alla fonte ora, quindi ti dirò cosa ho trovato.
Rudolf,

Se assegno correttamente un menu, funziona!
Rudolf,

Risposte:


18

Ottengo questo errore quando non ci sono menu definiti o nessun menu impostato per la posizione in Appearance->Menus. Quando ciò si verifica, wp_nav_menuutilizza un fallback del camminatore di pagina.

  1. Il fallback (predefinito) perwp_nav_menu èwp_walker_page
  2. quale usa wp_page_menu
  3. quale usa wp_list_pages
  4. quale usa walk_page_tree
  5. che Walker_Pagenon usa Walker_Nav_Menu.

E a quanto pare i due camminatori non sono compatibili. Non so perché non fallisca con grazia. Mi sembra un insetto.

Con un menu impostato su wp-admin->Appearance->Menus, il tuo codice funziona.

È possibile evitare l'errore verificando che sia presente un menu assegnato alla posizione prima di provare a utilizzare la posizione.

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

Oppure, se preferisci meno codice aggiuntivo antistaminico (grazie @Rarst):

if (has_nav_menu('primary')) {
  wp_nav_menu( array(
      'theme_location' => 'primary',
      'walker'         => new Walker_Nav_Menu_With_Aria,
  ) );
}

Il fallback viene utilizzato solo quando tutto il resto non riesce a visualizzare le pagine. Se il menu funziona correttamente, vengono visualizzate le voci walk_nav_menu_tree()utilizzate Walker_Nav_Menuper impostazione predefinita.
Rarst

Bel aggiornamento! Non mi è venuto in mente che la funzione errata potrebbe essere afferrare il camminatore (che è meh). Inoltre c'è has_nav_menu()per quel controllo.
Rarst

Questo è esattamente ciò che volevo solo postare: D Il menu di navigazione $argsviene convertito in un oggetto nella wp-includes/nav-menu-template.phpriga 145 dalla wp_nav_menu()funzione. La wp_page_menu()funzione utilizzata come fallback non lo fa, ma passa semplicemente l'array al Walker dal menu di navigazione che necessita dell'oggetto. Se aggiungi semplicemente $args = (object) $argsa all'inizio della start_elfunzione della classe Walker, puoi risolverlo. Dove sarebbe il posto giusto per segnalarlo al team di WordPress?
Rudolf,

I bug di base di @Rudolf dovrebbero essere segnalati su core.trac.wordpress.org
Rarst

Anche l' WP_Postoggetto che viene passato $itemè diverso (per questo motivo, le pagine non hanno nomi e l'elenco è composto solo da <li>elementi vuoti ). Sarebbe necessario un serio refactoring per rendere compatibili questi due walker.
Rudolf,

0

usa il codice qui sotto per riparare:

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;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.