1

I am trying to understand the wp_nav_menufunction and i am okay with its arguments but wordpress states to use int , string and WP_Term with the menu key. I need to know how to use the WP_Term with it because wordpress just offers the core class WP_Term.You can just explain the concept if you want. Why and What the result of using it?

2

Background

As you already know, wp_nav_menu() function takes an array $args as argument & menu is one of the keys to that $args array.

The key menu for the argument $args is defined as:

(int|string|WP_Term) Desired menu. Accepts (matching in order) id, slug, name, menu object.

Now, if you look deep into the implementation of wp_nav_menu() function, you'll see that, no matter what value you provide, whether it is an int id, a string name, a string slug or an object WP_Term, it'll always retrieve the WP_Term object for the corresponding menu id | name | slug before creating the menu.

For example: if you have a menu with id 3, name My Menu and slug my-menu; you can add that menu using any of the following CODE:

    // with id: 3
    wp_nav_menu( array(
        'menu'           => 3
    ) );

    // with name: My Menu
    wp_nav_menu( array(
        'menu'           => "My Menu"
    ) );

    // with slug: my-menu
    wp_nav_menu( array(
        'menu'           => "my-menu"
    ) );

Even if you don't provide the menu argument, it'll try to get the WP_Term object from other arguments like theme_location.

For example: say the menu location top was registered using register_nav_menus() function in your theme's functions.php file & the menu named My Menu was asigned to the top location from your WP admin panel. In that case, you can get the same menu using:

    wp_nav_menu( array(
        'theme_location' => 'top'
    ) );

In each of the above cases, wp_nav_menu() function retrieves the WP_Term object before generating the menu. It uses the wp_get_nav_menu_object() function to do so.

Implementation

So instead of theme_location argument, or menu argument as int id or string name | slug, you can directly provide the corresponding WP_Term object.

One way get the WP_Term object is by using the WP_Term::get_instance() method:

    // get the WP_Term object using menu id 3
    $menu_obj = WP_Term::get_instance( 3, 'nav_menu' );

You can also get the WP_Term object with menu name | slug using get_term_by() function:

    // by menu slug
    $menu_obj = get_term_by( 'slug', 'my-menu', 'nav_menu' );

    // or, by menu name
    $menu_obj = get_term_by( 'name', 'My Menu', 'nav_menu' );

Now that you've got the WP_Term object $menu_obj, you can use that to generate the menu:

    wp_nav_menu( array(
        'menu'           => $menu_obj
    ) );

Use case:

So you know how to generate a menu using WP_Term object as an argument to wp_nav_menu() function. Now the question is: why will you want to use it? Apart from the fact that it's just another option, you may want to use it because it may be a slightly faster option.

For example, if you want to use the same menu twice, once in the header & then in the footer, in that case, instead of using menu id | slug | name, you may create WP_Term object in your template for header menu:

    global $menu_obj;
    $menu_obj = WP_Term::get_instance( 3, 'nav_menu' );

    wp_nav_menu( array(
        'menu'           => $menu_obj,
        'menu_id'        => 'header_menu'
    ) );

and then simply use $menu_obj in the footer template as well:

    // global declaration is needed to access the global variable from another template
    global $menu_obj;
    wp_nav_menu( array(
        'menu'           => $menu_obj,
        'menu_id'        => 'footer_menu'
    ) );

If you look into the implementation of wp_nav_menu() function, you'll see that by doing it this way, you will avoid a few extra function calls in WordPress core, thus the total execution will be slightly faster.

However, please remember that using theme_location argument or other options may be more convenient & better for maintenance. So whether or not you should use it totally depends on your own particular scenario. I just explained that you can & how, nothing more.

5
  • 1
    Wooooooooooow, I am amazed of this great answer... I really thank you for not only you have made me understand but also you took from your time to present this in detail answer, because i just realized that this is not easy question to answer. Feb 5 '17 at 16:41
  • I really appreciate you effort, thank you very much Feb 5 '17 at 16:43
  • 1
    I was going to answer in short, then I realized that others may benefit from it in the future as well. Thus the long answer. You are welcome.
    – Fayaz
    Feb 5 '17 at 16:45
  • You've done a great job here, and indeed it will be a benefit for many because no more details about this topic Feb 5 '17 at 16:48
  • This is very good! maybe to mention that the filter 'wp_nav_menu_args' starts before the arguments are turned into a 'WP_Term' (nav-menu-template.php L71) So checking against an ID or Name can be different when menus are created in the backend (WP_Term) or in a template(all possibilities). Sep 4 '17 at 16:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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