Auto Generate Nav Menus on Theme Activation in WordPress

If you are building a theme in WordPress and you want to automatically generate nav menus on theme activation, here is how you can do it:

We need two functions to make it easier for us to auto generate nav menus and menu items:

Menu Item Generator Function:

1
2
3
4
5
6
7
8
9
function generate_site_nav_menu_item( $term_id, $title, $url ) {
   
    wp_update_nav_menu_item($term_id, 0, array(
        'menu-item-title'   =>  sprintf( __('%s', 'text_domain'), $title ),
        'menu-item-url'     =>  home_url( '/' . $url ),
        'menu-item-status'  =>  'publish'
    ) );
   
}
  • The function above will automatically generate a “Custom Link” that points to the page we specify on the $url parameter.

Menu Generator Function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function generate_site_nav_menu( $menu_name, $menu_items_array, $location_target ) {
   
    $menu_primary = $menu_name;
    wp_create_nav_menu( $menu_primary );
    $menu_primary_obj = get_term_by( 'name', $menu_primary, 'nav_menu' );
   
    foreach( $menu_items_array as $page_name => $page_location ){
        generate_site_nav_menu_item( $menu_primary_obj->term_id, $page_name, $page_location );
    }
   
    $locations_primary_arr = get_theme_mod( 'nav_menu_locations' );
    $locations_primary_arr[$location_target] = $menu_primary_obj->term_id;
    set_theme_mod( 'nav_menu_locations', $locations_primary_arr );
       
    update_option( 'menu_check', true );
   
}

Usage

Example let’s create two Header menus, menu 1 will be shown to Logged in users and menu 2 will be shown to visitors only

Register 2 Navigations: primary and secondary

1
2
3
4
5
6
7
8
9
10
11
12
function my_after_setup_theme() {

    /**
     * Register Navigations
     */

    register_nav_menus( array(
        'primary'   => __('Primary Navigation', 'text_domain'),
        'secondary' => __('Secondary Navigation', 'text_domain')
    ) );   
   
}
add_action( 'after_setup_theme', 'my_after_setup_theme') );

Register your menu and menu items:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**
 * Runs when user switches to your custom theme
 *
 */

function my_after_switch_theme() {
/**
 * Setup the site navigation
 */
   
    $run_menu_maker_once = get_option('menu_check');

    if ( ! $run_menu_maker_once ){
        /**
         * Setup Navigation for : Header Menu - Logged In
         */
   
        $primary_menu_items = array(
            'Listings'  =>  'listings',
            'Submit Ad' =>  'submit-ad',       
            'Messages'  =>  'messages',
            'Account'   =>  'account',
            'Logout'    =>  'account?action=logout' // You need to setup your logout url using wp_logout()
        );
        cvf_generate_site_nav_menu( 'Header Menu - Logged In', $primary_menu_items, 'primary' );
       
        /**
         * Setup Navigation for : Header Menu - Logged Out
         */

        $secondary_menu_items = array(
            'Listings'  =>  'listings',
            'Submit Ad' =>  'submit-ad',           
            'Register'  =>  'register',
            'Login'     =>  'login'
        );
        cvf_generate_site_nav_menu( 'Header Menu - Logged Out', $secondary_menu_items, 'secondary' );
    }
}
add_action( 'after_switch_theme', 'my_after_switch_theme') );
  • Function above will execute when you switch / activate your theme.
  • Will be executed only when option “menu_check” is not equal to 1.

In your header.php, use the following code to output the menus for logged-in users or visitors only:

1
2
3
4
5
<?php if( is_user_logged_in() ): ?>
    <?php wp_nav_menu( array('theme_location' => 'primary', 'fallback_cb' => 'fallback_menu_pages' ) ); ?>
<?php else: ?>
    <?php wp_nav_menu( array('theme_location' => 'secondary', 'fallback_cb' => 'fallback_menu_pages' ) ); ?>
<?php endif; ?>

If you notice we added a fallback, which is the function that will be called if our menu (primary / secondary) is not existing. Add this fallback function to your functions.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function fallback_menu_pages() {
   
    $list_pages = '';
    $args = array(
        'sort_order' => 'asc',
        'sort_column' => 'post_title',
        'hierarchical' => 1,
        'child_of' => 0,
        'parent' => -1,
        'offset' => 0,
        'number' => 5,
        'post_type' => 'page',
        'post_status' => 'publish'
    ); 
    $pages = get_pages( $args );
       
    foreach( $pages as $key => $page ){
        $list_pages .= '<li><a href = "' . get_permalink( $page->ID ) . '">' . $page->post_title . '</a></li>';
    }
   
    echo $list_pages;
   
}
  • The function above will output only 5 menu items. – To change this, set “number” to the number of menu items you want to output.


Do you need help with a project? or have a new project in mind that you need help with?

Contact Me