Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I generate a custom menu/sub-menu system using wp_get_nav_menu_items in WordPress?

I have an html structure that requires customization of the wp_nav_menu code.

This is the html I need to generate:

<ul class="main-nav">     <li class="item">         <a href="http://example.com/?p=123" class="title">Title</a>         <a href="http://example.com/?p=123" class="desc">Description</a>         <ul class="sub-menu">             <li class="item">                 <a href="http://example.com/?p=123" class="title">Title</a>                 <a href="http://example.com/?p=123" class="desc">Description</a>             </li>         </ul>     </li>      <li class="item">         <a href="http://example.com/?p=123" class="title">Title</a>         <a href="http://example.com/?p=123" class="desc">Description</a>     </li> </ul> 

I am currently using wp_get_nav_menu_items to get all the items from my menu as an array.

Right now I am able to generate the above html without the sub-menus using the following code:

<?php  $menu_name = 'main-nav'; $locations = get_nav_menu_locations() $menu = wp_get_nav_menu_object( $locations[ $menu_name ] ); $menuitems = wp_get_nav_menu_items( $menu->term_id, array( 'order' => 'DESC' ) );  foreach ( $menuitems as $item ):      $id = get_post_meta( $item->ID, '_menu_item_object_id', true );     $page = get_page( $id );     $link = get_page_link( $id ); ?>      <li class="item">         <a href="<?php echo $link; ?>" class="title">             <?php echo $page->post_title; ?>         </a>         <a href="<?php echo $link; ?>" class="desc">             <?php echo $page->post_excerpt; ?>         </a>     </li>  <?php endforeach; ?> 

I would have generated the menu using the wp_nav_menu function but I still need the description shown using $page->post_excerpt.

I've found that there is a property for each item called $item->menu_item_parent which gives the ID of the parent menu item.

How would I generate the sub-menu in my foreach loop? Or is there a really simple way using wp_nav_menu which Google forgot to mention?

like image 756
hitautodestruct Avatar asked Aug 13 '12 13:08

hitautodestruct


People also ask

How do I create a custom sub menu in WordPress?

To add it on one of the plugin's parent menu, use add_submenu_page() and set the priority of your add_action() to lower i.e, above 10. Then in add_submenu_page(), replace 'plugin-parent-menu-slug' with the slug of the parent menu where you want it to add.

How do I get all Menus in WordPress?

Get it done in simple way! The code snippet is very simple as the following: $menus = get_terms( 'nav_menu' ); $menus = array_combine( wp_list_pluck( $menus, 'term_id' ), wp_list_pluck( $menus, 'name' ) ); print_r( $menus ); // You'll get: // array( 'menu_id' => 'Menu Name' );

How to create a custom navigation menu in WordPress?

Here is an example of what a navigation menu looks like: Thankfully, with the WordPress drag-and-drop menu interface, creating drop-down menus is pretty easy. With that in mind, let’s see a step-by-step guide on how to create a custom menu. To begin, login to your WordPress admin dashboard. Next, go to Appearance >> Menus.

What is a WordPress menu and how to create one?

Your WordPress menu is essentially a map of your website. When it’s well designed, customers can use it to browse your site with ease to find exactly what they’re looking for. In this post, we’ll introduce you to WordPress custom menus and walk you through how to create one in four easy steps.

Is it easy to create drop-down menus in WordPress?

Thankfully, with the WordPress drag-and-drop menu interface, creating drop-down menus is pretty easy. With that in mind, let’s see a step-by-step guide on how to create a custom menu.

What are the best WordPress menu plugins?

However, if you want extra menu functionality added to your site, there are many WordPress Menu plugins such as UberMenu and Superfly to help with that. With these plugins, you get to create large mega menus. You can also add animation effects, images, and videos to your menu.


1 Answers

For anyone who tackles something similar here's my solution:

Quick code example on a gist

Here's the code on a github gist for anyone who wants to get in on the copy paste action.

TL;DR

TL;DR Loop over list, drill down if there's a sub menu, close if we reach the end of the sub menu and menu.

Complete Code explanation

Firstly get the menu items as a flat array:

<?php $menu_name = 'main_nav'; $locations = get_nav_menu_locations(); $menu = wp_get_nav_menu_object( $locations[ $menu_name ] ); $menuitems = wp_get_nav_menu_items( $menu->term_id, array( 'order' => 'DESC' ) ); ?> 

Then iterate over the array of the menu items:

<nav> <ul class="main-nav">     <?php     $count = 0;     $submenu = false;      foreach( $menuitems as $item ):         // set up title and url         $title = $item->title;         $link = $item->url;          // item does not have a parent so menu_item_parent equals 0 (false)         if ( !$item->menu_item_parent ):          // save this id for later comparison with sub-menu items         $parent_id = $item->ID;     ?> 

Write the first parent item <li>:

    <li class="item">         <a href="<?php echo $link; ?>" class="title">             <?php echo $title; ?>         </a>     <?php endif; ?> 

Check that this items' parent id matches the stored parent id:

        <?php if ( $parent_id == $item->menu_item_parent ): ?> 

Start sub-menu <ul> and set $submenu flag to true for later referance:

            <?php if ( !$submenu ): $submenu = true; ?>             <ul class="sub-menu">             <?php endif; ?> 

Write the sub-menu item:

                <li class="item">                     <a href="<?php echo $link; ?>" class="title"><?php echo $title; ?></a>                 </li> 

If the next item does not have the same parent id and we have a sub-menu declared then close the sub-menu <ul>

            <?php if ( $menuitems[ $count + 1 ]->menu_item_parent != $parent_id && $submenu ): ?>             </ul>             <?php $submenu = false; endif; ?>          <?php endif; ?> 

Again, if the next item in the array does not have the same parent id close the <li>

    <?php if ( $menuitems[ $count + 1 ]->menu_item_parent != $parent_id ): ?>     </li>                                <?php $submenu = false; endif; ?>  <?php $count++; endforeach; ?>    </ul> </nav> 
like image 195
hitautodestruct Avatar answered Sep 22 '22 14:09

hitautodestruct