I have a custom menu using the new Menu System but it is not returning in the correct order. I have no idea what order its in - its not alphabetical, or by date, or by any pattern I can see.

The link is http://www.oia.co.za/.

The pages "sponsors", "archives" and "fewtchafests" are supposed to appear as the last 3 items, after the series of numbers, not before them. If the first item wasn't also a number, I might think it was rendering all numbers last, but that first item ("8333") kind of scuppers that idea.

Screenshot of correctly dragged-and-dropped menu order attached, screenshot of website displaying wrong order attached, and the code used to call the menu is below.

correct menu order

enter image description here

    <nav role="navigation">
            wp_nav_menu( array(
                'theme_location' => 'advent-calendar',
                'menu' => 'advent-calendar',
                'menu_class' => 'component-calendar',
                'container_id' => 'calendar',
                'container_class' => 'advent',
                'orderby' => 'menu_order',
                'walker'=> new Salamander_Advent_Walker()

EDIT: It's definitely a problem with my custom walker (code below) - if I comment out the call to the custom walker function, it generates in the right order:

    class Salamander_Advent_Walker extends Walker_page {
        function start_el(&$output, $item, $depth, $args) {
           private $color_idx = 1;

            $advent_thumbnail = get_post_meta($item->object_id, 'advent-thumb', true);
            $advent_slug = get_post_meta($item->object_id, 'advent-slug', true);
            $advent_oneliner = get_post_meta($item->object_id, 'advent-oneliner', true);
            $advent_color = get_post_meta($item->object_id, 'advent-color', true);
            $advent_small_title = get_post_meta($item->object_id, 'advent-title', true);

            $advent_title = ( !empty($advent_small_title) ? $advent_small_title : $advent_slug);

            $output .= $indent . '
                        <li class="color'.$this->color_idx.' active">
                        <a href="#day'. $advent_slug .'">
                            <span class="day">
                                <strong>'. $advent_slug .'</strong>
                            <span class="content">
                                <small class="'. $advent_color .'">'. $advent_title .'</small>
                                <img src="'. $advent_thumbnail .'" width="126" height="91" alt="advent" />
                                <strong>'. $advent_oneliner .'</strong>
            if ($this->color_idx > 4) {
                $this->color_idx = 1;
        } // ends function
    } // ends class
  • Do you have a custom menu defined AND assigned to this theme_location, or is the output being generated by the fallback? Mar 9, 2012 at 15:48
  • @ChipBennett Yes, custom menu defined and location assigned. Mar 20, 2012 at 11:24
  • 4
    okay, next step: remove the custom walker argument, and verify whether the menu renders properly or not. If it does, then the problem is your custom walker. Mar 20, 2012 at 13:02
  • 1
    :) Yes, it's definitely the walker (and you have me thinking "Why didn't I think of that myself?") Mar 20, 2012 at 14:10

1 Answer 1


AFAIK there's a non-documented orderby parameter, that can be set to menu_order.

Edit: Straight from core, inside /wp-includes/nav-menu-template.php Line# 195 (WP 3.3.1):

$sorted_menu_items = array();
foreach ( (array) $menu_items as $key => $menu_item )
    $sorted_menu_items[$menu_item->menu_order] = $menu_item;

It's the lines immediately before the Walker runs. So the set menu_order should affect the order. You'll just have to set it inside your page from the meta box.

In short: You shouldn't need a custom Walker at all.


  • You don't have to use that $indent. It make really no sense as it's only for the source code.
  • You don't have to make it that hard to save your meta data into single vars. Also would this add lots of queries if they're currently not cached. Do it the following way:

    extract( get_post_custom( $item->object_id ), EXTR_SKIP );

Edit: extract simply makes single variables out of your custom meta data. The key is then the new name of your variable. EXTR_SKIP cares about making the variables unique as it skips double keys.

// Example: Structure of your post custom/meta data
    [0] => array( 'example_key_name' => array( 'example_value' ) )
    [1] => array( 'another_key_name' => 'another_value' )
// Becomes:
$example_key_name = array( 0 => 'example_value' );
// Value can now be called as:
// Becomes:
$another_key_name = 'another_value';
// Value can be called as:

The last example is not really possible, as you normally got serialized arrays as custom values (even for single values). So you'll always have to append [0] to your variable. But this technique def. shortens code. Especially if you got really large sets of meta data per post/CPT.

  • Thanks - I've included the orderby parameter, but it didn't change anything. Thanks for the note about $indent (I do like my source-code to look neat, but that's just because I'm anal). How do I use the extract() function, or rather, how do I assign variables like $advent_thumbnail etc for use later if I use extract()? Mar 20, 2012 at 11:32
  • @Amanda See (both) edits.
    – kaiser
    Mar 20, 2012 at 16:02
  • @Amanda Still following?
    – kaiser
    Mar 26, 2012 at 20:25
  • Hi - thanks, I understand the extract now... regarding not needing a custom walker - I had thought that would be the easiest way to retrieve a bunch of custom meta for display? "You'll just have to set it inside your page from the meta box." My home page isn't actually a "page", so there is no custom meta box to set menu order - the site is set to display "Latest Posts" in the settings, and this odd front page is managed by home.php. Mar 26, 2012 at 21:18
  • 1
    Could you go into core, and add echo '<pre>'; print_r($sorted_menu_items); echo '</pre>'; right below the lines I quoted from core ↑, then reload the page and post the result here? Thanks.
    – kaiser
    Mar 27, 2012 at 11:00

Your Answer

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

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