I’m trying to replace the walker argument from new My_Walker_Nav_Menu() to a string 'My_Walker_Nav_Menu' in this wp_nav_menu call (which works as is)

wp_nav_menu(
     array(
           'theme_location'    => 'header_nav',
           'menu_class'             => 'main-menu',
           'container'         => '',
           'fallback_cb'       => false,
           'walker' => new My_Walker_Nav_Menu()
           )
     );

When I change it to a string I’m getting this error Fatal error: Using $this when not in object context

The class is basic:

class My_Walker_Nav_Menu extends Walker_Nav_Menu {
    function start_lvl(&$output, $depth = 0, $args = Array()) {
        $indent = str_repeat("\t", $depth);
        if('header_nav' == $args->theme_location ){
            $output .='<span class="toggle-submenu fa fa-angle-down"></span>';
        }
        $output .= "\n$indent<ul class=\"sub-menu\">\n";
    }
}

I need to do this because apparently Customizer’s partial refresh doesn’t work with custom walkers.

When the Customizer determines it can’t do a partial refresh, it falls back to performing a full page refresh. Conditions for why a menu change will get a full page refresh include:

  • or if wp_nav_menu() is called with with a walker object instance, as opposed to a class name string;

Somebody else had this issue (mentioned in a comment) but didn’t get an answer.
I’ve searched through the docs but can’t seem to find anything.

Any help is much appreciated.

1 Answer
1

Apparently custom nav menu walkers are not supported though they were supposed to be. I’m surprised this only has been discovered now. However, there is an easy fix for you to get them to work. Just add this to your theme:

add_filter( 'wp_nav_menu_args', function( $args ) {
    if ( isset( $args['walker'] ) && is_string( $args['walker'] ) && class_exists( $args['walker'] ) ) {
        $args['walker'] = new $args['walker'];
    }
    return $args;
}, 1001 ); // 1001 because \WP_Customize_Nav_Menus::filter_wp_nav_menu_args() runs at 1000.

The following core patch would eliminate the need for this filter:

--- src/wp-includes/nav-menu-template.php
+++ src/wp-includes/nav-menu-template.php
@@ -526,6 +526,9 @@ function _wp_menu_item_classes_by_context( &$menu_items ) {
  */
 function walk_nav_menu_tree( $items, $depth, $r ) {
    $walker = ( empty($r->walker) ) ? new Walker_Nav_Menu : $r->walker;
+   if ( is_string( $walker ) && class_exists( $walker ) ) {
+       $walker = new $walker();
+   }
    $args = array( $items, $depth, $r );

    return call_user_func_array( array( $walker, 'walk' ), $args );

Leave a Reply

Your email address will not be published. Required fields are marked *