The right way of dealing wp_nav_menu fallback function – List custom categories & pages

So, this post succeeds our explanation on WordPress custom Nav menus. We’ve seen previously how we can use wp_nav_menu function to show user defined menus in the theme. But what if the user doesn’t provide any menu to the theme location? WordPress will then use the fallback function to write a default menu. wp_page_menu is used by default which just prints all the pages of your blog. In many situations, especially while developing themes, you might not want this to happen. You might want to give the user more refined way to control the output of the default navigation menu. You might want to display specific pages along with specific categories. You might also want to include the Home button and our famous dynamic login/logout button to the navigation. In such cases, you will need to write your own fallback function from scratch. Today we shall see, the right way of writing the fallback with various customization option. We shall also add Home button to it, give it proper class, list the pages we want (hierarchically) along with hierarchical categories.

#1: Registering the Nav menu:

As usual, we register our primary nav menu like this:

/**
 * The function which registers the primary nav menu
 * @uses register_nav_menus
 * @see http://codex.wordpress.org/Function_Reference/register_nav_menus
 */
function reg_primary_nav() {
    register_nav_menus(array(
        'primary' => 'Primary Menu',
    ));
}
//hook it to init
add_action('init', 'reg_primary_nav');

#2: Calling the API with custom fallback:

In order to do that, we need to discuss the arguments of wp_nav_menu. The one we will be using is fallback_cb which corresponds to the name of the fallback function. Keeping other arguments default we call it like this:

/**
 * Call the wp_nav_menu API to print the navigation menu
 * We will use a custom fallback function primary_menu_fallback
 * passed in as an argument
 *
 * @see http://codex.wordpress.org/Function_Reference/wp_nav_menu
 */
wp_nav_menu(array(
    'theme_location' => 'primary', //corresponds to the location as on register_nav_menus
    'container_class' => 'primary-nav', //custom class for styling purposes
    'fallback_cb' => 'primary_menu_fallback',
));

What next? Yes, you have guessed it right. We will be writing our primary_menu_fallback function which we have passed to the wp_nav_menu as an argument.

#3: Writing the fallback function:

We write in our fallback function keeping in mind 4 things:

  1. Add Home button with custom class (current on home page) for styling.
  2. Add the pages we want in specific number of tiers.
  3. Add the categories we want in specific number of tiers.
  4. Add our dynamic login/logout button.
<?php
/**
 * The fallback function for the primary nav menu
 *
 * It is capable of doing 4 custom navigation
 * 1. Home button
 * 2. List the pages you want
 * 3. List the categories you want
 * 4. Add dynamic login/logout & site admin button
 *
 * Check the inline comments for understanding how it works
 */
function primary_menu_fallback() {
    ?>
<div id="primary" class="primary-nav">
    <ul class="menu">
        <?php /* add home button */ ?>
        <li class="home <?php if(is_home() || is_front_page()) echo 'current_page_item'; ?>"><a href="<?php bloginfo('url'); ?>">Home</a></li>
        <?php
        /**
         * Show the pages we want
         * We shall be using wp_list_pages
         * For a list of arguments
         * @see http://codex.wordpress.org/Function_Reference/wp_list_pages
         */
        wp_list_pages(array(
            'depth' => 2, //number of tiers, 0 for unlimited
            'exclude' => '', //comma seperated IDs of pages you want to exclude
            'title_li' => '', //must override it to empty string so that it does not break our nav
            'sort_column' => 'post_title', //see documentation for other possibilites
            'sort_order' => 'ASC', //ASCending or DESCending
        ));
        ?>
        <?php
        /**
         * Show the categories we want
         * We shall be using wp_list_categories
         * For a list of arguments
         * @see http://codex.wordpress.org/Template_Tags/wp_list_categories
         */
        wp_list_categories(array(
            'orderby' => 'name', //see documentation for more sorting possibilites
            'order' => 'ASC', //ASCending or DESCending
            'exclude' => '', //comma seperated IDs of categories you want to exclude
            'title_li' => '', //must override it to empty string so that it does not break our nav
            'depth' => 2, //number of tiers, 0 for unlimited
            'hide_empty' => 1, //hides empty categories if 1, pass 0 to show
        ));
        ?>
        <?php
        /**
         * Add our dynamic login/logout & Site Admin buttons
         * @see https://www.intechgrity.com/add-dynamic-login-logout-n-site-admin-button-to-wordpress-using-wp-api/
         */
        ?>
        <li class="login"><?php wp_loginout(); ?></li>
        <?php wp_register('<li class="admin">'); ?>
    </ul>
</div>
    <?php
}

So now the wp_nav_menu will first try to output user’s own menu if provided, else will fallback to your own function. This is the most sophisticated way of handling the fallback. In our next chapter, we shall see how we can directly hook into wp_nav_menu to even customize the user’s own menu dynamically. Till then, have fun with the fallback. Be creative and show us what fallback are you falling for?

2 comments

Leave a Reply