Using string instead of object class instantiation on the walker argument breaks wp_nav_menu

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 Comment