So, I've been trying to write a plugin, and I need to use the 'nav_menu_link_attributes' filter. I tried adding the filter, but it didn't respond - at all. That is, I made it die mid-process once the filter was called.

# in class definition

public function __construct() {

public function filter_menuitem($attrs) {


I looked at the source for nav-menu-template.php to see what filters were called for what, and when. So, I tried using the following filters, one at a time, in the order they appear in the source; some worked, some didn't respond at all:

function wp_nav_menu() {
  wp_nav_menu_args                   Responded
  pre_wp_nav_menu                    Responded
  wp_nav_menu_container_allowedtags  Did not respond - not a surprise
  wp_nav_menu_objects                Did not respond - should definitely have responded
  wp_nav_menu_items                  Did not respond - should definitely have responded
  wp_nav_menu                        Did not respond - should definitely have responded

The only catch that would've made sense was that the 'pre_wp_nav_menu' can be used to generate a custom menu, skipping the WP default method which calls the following filters. But I tried using 3 different themes, and wouldn't expect that to be the case often, or even ever.

Am I missing something? Is this a WordPress bug? Is custom menu generation really that common?

WordPress 4.4.2
Tested Themes: Elegant Themes Divi, Twenty Thirteen, Twenty Fifteen
Plugins: Only my own, none of which use the 'pre_wp_nav_menu' filter

So, on @Pieter Goosen's answer, I looked in the source of the wp_nav_menu function, and found the 'wp_page_menu' filter which is called on the full HTML code (no newlines; includes wrappers) once it's composed. For the context of what I'm doing it's sufficient, and after hooking and testing it, I found it works!

I also found the 'wp_list_pages' filter works as well. Instead of the full HTML with all the tags, it only lists the <li> tags separated by newlines. No wrappers are included, not even the <ul> tag. I am skeptical, however, as to what else might be using this function. It may not be invoked only for the menu. Thus, to be safe, it might be better to stick with the 'wp_page_menu' filter.


1 Answer 1


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

  • My pleasure, enjoy. ;-) Commented Mar 10, 2016 at 4:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.