WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I need a way to create a custom HTML template for the wp_nav_menu function. I've heard of custom walker classes, but these don't appear to be helpful enough to achieve what I'm trying to do; at least as far as I know because of the lack of documentation towards walker functions. What I need to do is be able to add a 'hoverable' class to all top level menu items. I only need the menu to go two levels; top level, then child menu items. I need to add a 'top-level' class to all menu item anchor elements who have a sub-menu. I need all sub-menu lists to have the class 'sub-nav'. And I need to have all of the last sub-menu list items (li) to have a class 'last'.

Here's the code I have right now that generates my menu the exact way I need it to be generated using the get_pages function:

$pages = get_pages(array(
    'parent' => 0,
    'sort_order' => 'ASC',
    'sort_column' => 'menu_order'

$num_pages = count($pages);
$p = 0;

$exclude = '"pastor.php","service.php","gallery.php","audio.php","video.php"';
$exclude_list = $wpdb->get_results("SELECT GROUP_CONCAT(t1.ID) AS IDS FROM " . $wpdb->posts . " AS t1 INNER JOIN " . $wpdb->postmeta . " AS t2 ON (t1.ID = t2.post_id) WHERE t1.post_type = 'page' AND (t1.post_status = 'publish' OR t1.post_status = 'private') AND t2.meta_key = '_wp_page_template' AND t2.meta_value IN (" . $exclude . ")  ORDER BY t1.post_date DESC");

foreach($pages as &$page) :
    $children = get_pages(array(
        'sort_order' => 'ASC',
        'sort_column' => 'menu_order',
        'hierarchical' => 0,
        'childof' => $page->ID,
        'parent' => $page->ID,
        'exclude' => $exclude_list[0]->IDS
    $num_children = count($children);
    $has_children = $num_children > 0;
    <li class="nav-item<?php echo ($has_children ? ' hoverable' : '') . ($num_pages == ++$p ? ' last' : '') . ($page->post_name === $root_parent->post_name ? ' active' : '')?>">
        <a href="<?php echo get_page_link($page->ID)?>" class="top-level"><?php echo $page->post_title?></a>

        <?php if($has_children) : ?>
            <ul class="sub-nav">
                $c = 0;
                foreach($children as &$child) : ?>
                    <li class="nav-item<?php echo ($num_children == ++$c ? ' last' : '')?>">
                        <a href="<?php echo get_page_link($child->ID)?>"><?php echo $child->post_title?></a>
                <?php endforeach;?>
        <?php endif;?>

Is there a way to pull menu items in an order multi-dimensional array so that way I can just iterate through them and generate the above template manually, instead of all this wp_nav_menu and walker none-sense?

share|improve this question

Yes, there is. Use wp_get_nav_menu_items() instead.

<?php $items = wp_get_nav_menu_items( $menu, $args ); ?> 

<?php $args = array(
    'order'                  => 'ASC',
    'orderby'                => 'menu_order',
    'post_type'              => 'nav_menu_item',
    'post_status'            => 'publish',
    'output'                 => ARRAY_A,
    'output_key'             => 'menu_order',
    'nopaging'               => true,
    'update_post_term_cache' => false ); ?>

Here is the page on WordPress Codex

share|improve this answer
Yes, this'll return a one-di array, but you can use post_parent to show two level output. – amit Aug 14 '12 at 7:00
But, post_parent only tells me the post's parent, not the menu item's parent, or am I wrong? – Sam Aug 14 '12 at 7:52
There's menu_item_parent, which is what I'm looking for. However, I'll need to first run through the single dimension array and transform it into a multi-dimensional array manually. Too bad, WP doesn't do this for me. – Sam Aug 14 '12 at 7:54
AFAIK, there is no other build in function to get the content of a nav menu. So you will have to transform it manually. – ifdion Aug 14 '12 at 8:34

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.