Error "Intentando obtener propiedad de no objeto" con Custom Walker para wp_nav_menu

8

Estoy tratando de agregar algunas cosas relacionadas con ARIA a la función wp_nav_menu. Utilizo una clase de caminante personalizada para este propósito:

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

Acabo de copiar y pegar la clase Walker_Nav_Menu original y agregué cosas, pero recibo errores porque la variable $ args tratada como un objeto es realmente una matriz. Pero lo realmente extraño es que este error persiste, incluso si paso el andador original de esta manera:

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

Estos son los mensajes de error que recibo:

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

Las líneas se ven así (¡en el archivo 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;
Rudolf
fuente
¿Obtiene un error si no pasa al caminante? Los argumentos deben ser objeto, creo que eso es lo que dicen los documentos en línea y lo que wp_nav_menu()pasa.
Rarst
No, si solo uso la wp_nav_menu()función predeterminada sin un andador, funciona perfectamente. Sí, pero ¿por qué es una matriz entonces? Incluso lo var_dumpedité, ningún objeto.
Rudolf
No estoy seguro de lo que está sucediendo entonces, porque pasar new Walker_Nav_Menudebería comportarse de manera idéntica a no pasar walker. ¿Está sucediendo algo más, algún complemento que se conecte / manipule la funcionalidad del menú?
Rarst
Acabo de hacer algunas pruebas adicionales, y estoy seguro de que este es un error de WordPress. En mi caso, el menú de navegación que utilicé no estaba asignado en el backend. Por lo tanto, se utilizó el respaldo de las páginas de la lista, parece que la variable args es una matriz. Trazaré esto hasta la fuente ahora, luego te diré lo que encontré.
Rudolf
Si asigno correctamente un menú, ¡funciona!
Rudolf

Respuestas:

18

Recibo este error cuando no hay menús definidos o no hay menús establecidos para la ubicación en Appearance->Menus. Cuando eso ocurre, wp_nav_menuutiliza una página de reserva de walker.

  1. El respaldo (predeterminado) parawp_nav_menu eswp_walker_page
  2. que usa wp_page_menu
  3. que usa wp_list_pages
  4. que usa walk_page_tree
  5. que usa Walker_Pageno Walker_Nav_Menu.

Y aparentemente los dos caminantes no son compatibles. No sé por qué no falla con gracia. Eso me parece un error.

Con un menú establecido en wp-admin->Appearance->Menus, su código funciona.

Puede evitar el error verificando que haya un menú asignado a la ubicación antes de intentar usar la ubicación.

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

O, si prefiere menos código adicional antihistamínico (gracias @Rarst):

if (has_nav_menu('primary')) {
  wp_nav_menu( array(
      'theme_location' => 'primary',
      'walker'         => new Walker_Nav_Menu_With_Aria,
  ) );
}
s_ha_dum
fuente
Fallback solo se usa cuando todo lo demás no puede mostrar las páginas. Si el menú funciona correctamente, se recorren los elementos con los walk_nav_menu_tree()que se usa Walker_Nav_Menude forma predeterminada.
Rarst
Buena actualización! No se me ocurrió que una función incorrecta podría estar agarrando el andador (eso es meh). También hay has_nav_menu()para ese cheque.
Rarst
Eso es exactamente lo que quería publicar: D La función $argsconvierte el menú de navegación en un objeto en la wp-includes/nav-menu-template.phplínea 145 wp_nav_menu(). La wp_page_menu()función que se usa como reserva no hace eso, sino que simplemente pasa la matriz al Walker desde el menú de navegación que necesita el objeto. Si solo agrega un $args = (object) $argsen la parte superior de la start_elfunción de la clase Walker, puede solucionarlo. ¿Dónde sería el lugar adecuado para informar esto al equipo de WordPress?
Rudolf
Los errores principales de @Rudolf se deben informar en core.trac.wordpress.org
Rarst
El WP_Postobjeto que se pasa como también $itemes diferente (debido a esto, las páginas no tienen nombres y la lista solo consta de <li>elementos vacíos ). Sería necesaria una refactorización seria para hacer compatibles estos dos andadores.
Rudolf
0

use el siguiente código para reparar:

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
fuente