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.