How to Automatically Create WordPress Navigation Menu Items

November 18, 2015 10:59am

Let’s say you’ve got a custom theme (or a modified child theme) and you’re already registering navigation menus. Now you want to also automatically add the actual menu items to those navigation menus. Maybe you’ve got a Multisite install and every time someone creates a new site, you want their navigation all setup for them.

This is totally possible and I spent the morning figuring all of the intricacies out, thanks of course to some great support from the WordPress Codex and Stack Exchange.

Firstly, you register the nav menus in your functions.php file, something like this:

Next, we want to create all of the navigation items for the Primary menu. In the example below we’ll create both custom menu links, as well as automatically add some categories and make them sub-navigation items of a custom “Topics” item.

There you have it! What this code does is exactly what I’ve specified in the previous paragraph, and it all happens whenever you visit the Appearance > Menu page.

But let’s explain what’s going on here in a bit more detail.

We’re setting this all up as a function, and that function is auto_nav_creation_primary. In the line below, we add that function to the load-nav-menus.php hook, which fires when the Appearance > Menus screen is loaded. You could change this to something else, but note that you need to have already created some categories for that part to work.

In my application, I programmatically create the categories, too, before I create these nav menus. I’ll post on that some other day.

Here we define the name of our menu, and then using $menu_exists = wp_get_nav_menu_object($name); and the following line, we check to see if the menu exists already. No reason to create or overwrite it if it does (otherwise, every time you visited this screen you would rewrite your menu, so no manual changes could ever be made).

Next, we’ll create the “Topics” top-level, custom menu item I’d mentioned. This code can be edited to create any navigation item, linking to any URL, and even give it a custom CSS class.

wp_update_nav_menu_item($menu->term_id, 0, array(
'menu-item-title' => __('Topics'), // the name of the menu item
'menu-item-classes' => 'topics-dropdown', // a custom CSS class
'menu-item-url' => '#', // the URL, could be replaced with 'get_bloginfo('url')' if you want the homepage URL, or get_permalink('55'), where 55 is the ID of a particular page, if you want to have it be a link to some specific post or page
'menu-item-type' => 'custom',
'menu-item-status' => 'publish'));

Next, we’ll load up our categories and add them as sub-nav items to this ‘Topics’ item. In this case, I don’t want the Uncategorized category, and I’ve excluded a category with an ID of 10, too, so that we can show that outside of this dropdown (more on that below).

$cat_args=array(
'exclude' => '1,10', // exclude 1 (the Uncategorized category) and 10, another category we don't want in this sub-menu
'hide_empty' => 0 // I use this to force WordPress to return even empty categories, which get_categories doesn't do by default
);
$the_cats = get_categories($cat_args); // get the list of categories from our arguments above
if (count($the_cats) > 0){ // if the list isn't empty, let's do this!
foreach($the_cats as $category){
wp_update_nav_menu_item($menu->term_id, 0, array(
'menu-item-title' => $category->name, // the visible name of the item will be the category's name
'menu-item-object-id' => $category->term_id,
'menu-item-db-id' => 0, // 0 equates to setting a new ID for this item
'menu-item-object' => 'category',
'menu-item-parent-id' => 5, // here I know that 5 is the 'Topics' menu item ID, replace as needed. This makes each category a child of the Topics item
'menu-item-depth' => 1, // this sets the depth to 1, though it may not be necessary
'menu-item-type' => 'taxonomy', // this defines the type of menu item, where we used Custom before, we're now defining it as a taxonomy
'menu-item-url' => get_category_link($category->term_id), // sets the URL for the menu item
'menu-item-status' => 'publish',)
);
}
}

You can do something similar to only retrieve one category. In this case, I want a particular category to live as a top level nav item.

I would think the easiest way to do that would be to just go into the Appearance > Menu section, click the down arrow on the item you want to change, and then edit the title.

By default, if you choose Page type (for example), and add an “About” page, then later change its title to “About Me”, the nav item will auto-update. Editing it once (in Appearance > Menus) will prevent this from happening again.

You certainly could do this, you’d need to modify the code to include all pages. By default, if you don’t create a menu though WP will add all pages automatically to that particular menu, I do believe.

Wow! This is a really handy technique! I have a client who doesn’t like to do any tech work at all so it will be great that the menu will just be set up for similar people who are interested in my theme