Question

I have menus set corresponding to a custom field on a page. Ie I have menu1, menu2, and menu3 on three pages under custom field => MenuName. Under functions.php I have:

/* Add Menu Locations */
add_action( 'init', 'register_my_menus' );
function register_my_menus() {
    register_nav_menus(
        array(
            'one-menu' => __('menu1'),
            'two-menu' => __('menu2'),
            'three-menu' => __('menu3'),
            'footerBlocka' => __('Footer Block 1'),
            'footerBlockb' => __('Footer Block 2'),
            'footerBlockc' => __('Footer Block 3'),
            'footerBlockd' => __('Footer Block 5')
        )
    );
}

Then in my page template I have:

<?php
    /* Division */
    wp_nav_menu(array(
        'menu' => get_post_meta( $post->ID, 'MenuName', true),
        'depth' => 2,
        'container' => false,
        'menu_class' => 'nav navbar-nav'
    ));
?>

This works just fine as long as a) the menu exists and b) the menu actually contains menu items. If the menu exists but there are no menu items, it strangely displays a listing of all menu items from all menus on the site. If the menu does not exist, it just shows the next menu listed in functions.php.

So I think in my page template I need to check for the menu and if it exists then print the menu. I have seen a couple of other examples but all I could find were if the theme region exists or a menu exists. Since I'm using 'menu' => get_post_meta( $post->ID, 'MenuName', true), to call the menu dynamically, I don't know how to check this dynamic menu before trying to print the menu.

So how do I check the menu that is called from 'menu' => get_post_meta( $post->ID, 'MenuName', true), and if it exists and has menu items then print it, if not, print nothing?

EDIT: I tried the following:

<?php
    /* Division */
    wp_nav_menu(array(
        'menu' => get_post_meta( $post->ID, 'MenuName', true),
        'depth' => 2,
        'fallback_cb' => false,
        'container' => false,
        'menu_class' => 'nav navbar-nav'
    ));
?>

This new addition will still render the next menu in line from the functions.php function. So if menu3 does not exist, it prints the footerBlocka menu. I am thinking my goal is to check page ID for MenuName custom field, if it exists, then check whether the menu exists and has links, if true, then print menu, else do nothing. Something like:

$menu = get_post_meta($post->ID, 'MenuName');
if($menu){
  if([wp_nav_menu == $menu AND has links]){
      wp_nav_menu(array(...));
  }
}

That's the pseudo code I think would be needed but I don't know enough about the WordPress hooks to know what it needs to be.

Was it helpful?

Solution

wp_nav_menu has the argument fallback_cb, which is the function called if a menu doesn't exist. This is set to wp_page_menu by default, which is why you see a list of pages if the menu doesn't exist. If you explicitly set that to false, then nothing will be output if the menu doesn't exist.

EDIT-

Given a menu name, you can load the menu object with wp_get_nav_menu_object. This will tell you if it exists, what its ID is (to pass as menu argument), and how many menu items it has.

$menu_name = get_post_meta( $post->ID, 'MenuName', true );
$menu = wp_get_nav_menu_object( $menu_name );
if( is_object( $menu ) ){
    echo 'This menu exists!';
    echo 'This menu has ' . $menu->count . ' menu items.';
    echo 'This menu ID is ' . $menu->term_id . '.';
} else {
    echo 'A menu with that name doesn\'t exist';
}

OTHER TIPS

A simpler approach is to just use:

<?php if(wp_get_nav_menu_items(get_nav_menu_locations()['theme_location'])): ?>
    Do something here IF the menu location you used in the line above has any items
<?php endif; ?>
Licensed under: CC-BY-SA with attribution
Not affiliated with wordpress.stackexchange
scroll top