This has to do with the fallback_cb
argument in wp_nav_menu()
. Most nav menus do not set this parameter, so the default value is used, which is wp_page_menu
.
If you look at the source code of wp_nav_menu()
, with no fallback_cb
set (defualt wp_page_menu
), you will see the following lines of code executes
if ( ( !$menu || is_wp_error($menu) || ( isset($menu_items) && empty($menu_items) && !$args->theme_location ) )
&& isset( $args->fallback_cb ) && $args->fallback_cb && is_callable( $args->fallback_cb ) )
return call_user_func( $args->fallback_cb, (array) $args );
This code bails out and loads wp_page_menu()
. This code executes after the pre_wp_nav_menu
filter, that is why you see this filter executes. All filters after that few lines will not executes because wp_nav_menu()
has now loaded wp_page_menu()
.
If you now test the filters inside wp_page_menu()
, you will see that they fire as expected.
You can have a look at my answer here to see how I have used this to determine which filter to use