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?

  • Old question, but just FYI my answer here might help if trying to access the WP nav as an array.
    – Brad Adams
    Mar 8, 2018 at 14:11

1 Answer 1


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

  • Yes, this'll return a one-di array, but you can use post_parent to show two level output.
    – Amit Kosti
    Aug 14, 2012 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, 2012 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, 2012 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, 2012 at 8:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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