Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm looking to pass custom nav_menus through an RSS feed so I can grab them on other sites to create the same custom menu on multiple sites.

What I can't figure out by looking through the database is how WP is storing the data it needs to know which items are parent>child related for hierarchy. How does it know to output the "child" pages as a separate ul even if they aren't "officially" set as parent>child (from edit post screen), only visually in the Menus area?

I can look at just the post type of nav_menu_item in the database and the menu_order column lists the items in top to bottom order but nothing seems to reference the menu>submenu relationship.

Thanks for anything you can tell me.

share|improve this question
add comment

1 Answer

up vote 2 down vote accepted
  • Each nav menu item is stored a post type named nav_menu_item.
  • The horizontal position is stored in the column menu_order
  • The vertical position (hierarchy) is stored as post meta field named _menu_item_menu_item_parent holding the parent nav_menu_item ID.

To create nested lists WordPress looks for _menu_item_menu_item_parent on each item, and if there is an item with that ID those posts will be grouped in a new sub list. That is basically what the class Walker_Nav_Menu does.

To illustrate that, use a little plugin:

<?php
/**
 * Plugin Name: Inspect Nav Menu Items
 * Plugin URI:  http://wordpress.stackexchange.com/q/70872
 */

add_filter( 'wp_nav_menu_args', 'wpse_70872_inspect_nav_menu_items' );

function wpse_70872_inspect_nav_menu_items( $dummy = 1 )
{
    if ( 'wp_nav_menu_args' === current_filter() )
    {
        add_action( 'shutdown', __FUNCTION__ );
        return $dummy;
    }

    // If we made it so far this function was called on 'shutdown'.
    $nav_items = get_posts(
        array (
            'numberposts' => -1,
            'post_type'   => 'nav_menu_item'
        )
    );

    $out = array ();

    foreach ( $nav_items as $nav_item )
    {
        $out[] = array (
            // general post data
            'post_data' => $nav_item,
            // meta data
            'meta' => get_post_custom( $nav_item->ID ),
            // Name of the menu
            'terms' => wp_get_object_terms( $nav_item->ID, 'nav_menu' ),
        );
    }

    print '<pre>' . esc_html( var_export( $out, TRUE ) ) . '</pre>';
}

The result might look like this:

array (
  0 => 
  array (
    'post_data' => 
    stdClass::__set_state(array(
       'ID' => 695,
       'post_author' => '1',
       'post_date' => '2012-10-29 23:24:13',
       'post_date_gmt' => '2012-10-29 23:24:13',
       'post_content' => ' ',
       'post_title' => '',
       'post_excerpt' => '',
       'post_status' => 'publish',
       'comment_status' => 'open',
       'ping_status' => 'open',
       'post_password' => '',
       'post_name' => '695',
       'to_ping' => '',
       'pinged' => '',
       'post_modified' => '2012-10-29 23:24:13',
       'post_modified_gmt' => '2012-10-29 23:24:13',
       'post_content_filtered' => '',
       'post_parent' => 0,
       'guid' => 'http://wpse.mu.wp/?p=695',
       'menu_order' => 9,
       'post_type' => 'nav_menu_item',
       'post_mime_type' => '',
       'comment_count' => '0',
       'filter' => 'raw',
    )),
    'meta' => 
    array (
      '_menu_item_type' => 
      array (
        0 => 'taxonomy',
      ),
      '_menu_item_menu_item_parent' => 
      array (
        0 => '693',
      ),
      '_menu_item_object_id' => 
      array (
        0 => '12',
      ),
      '_menu_item_object' => 
      array (
        0 => 'category',
      ),
      '_menu_item_target' => 
      array (
        0 => '',
      ),
      '_menu_item_classes' => 
      array (
        0 => 'a:1:{i:0;s:0:"";}',
      ),
      '_menu_item_xfn' => 
      array (
        0 => '',
      ),
      '_menu_item_url' => 
      array (
        0 => '',
      ),
    ),
    'terms' => 
    array (
      0 => 
      stdClass::__set_state(array(
         'term_id' => '105',
         'name' => 'Test 1',
         'slug' => 'test-1',
         'term_group' => '0',
         'term_taxonomy_id' => '106',
         'taxonomy' => 'nav_menu',
         'description' => '',
         'parent' => '0',
         'count' => '9',
      )),
    ),
  ),
  1 => 
  array (
    'post_data' => 
    stdClass::__set_state(array(
       'ID' => 694,
       'post_author' => '1',
       'post_date' => '2012-10-29 23:24:12',
       'post_date_gmt' => '2012-10-29 23:24:12',
       'post_content' => ' ',
       'post_title' => '',
       'post_excerpt' => '',
       'post_status' => 'publish',
       'comment_status' => 'open',
       'ping_status' => 'open',
       'post_password' => '',
       'post_name' => '694',
       'to_ping' => '',
       'pinged' => '',
       'post_modified' => '2012-10-29 23:24:12',
       'post_modified_gmt' => '2012-10-29 23:24:12',
       'post_content_filtered' => '',
       'post_parent' => 0,
       'guid' => 'http://wpse.mu.wp/?p=694',
       'menu_order' => 8,
       'post_type' => 'nav_menu_item',
       'post_mime_type' => '',
       'comment_count' => '0',
       'filter' => 'raw',
    )),
    'meta' => 
    array (
      '_menu_item_type' => 
      array (
        0 => 'taxonomy',
      ),
      '_menu_item_menu_item_parent' => 
      array (
        0 => '693',
      ),
      '_menu_item_object_id' => 
      array (
        0 => '11',
      ),
      '_menu_item_object' => 
      array (
        0 => 'category',
      ),
      '_menu_item_target' => 
      array (
        0 => '',
      ),
      '_menu_item_classes' => 
      array (
        0 => 'a:1:{i:0;s:0:"";}',
      ),
      '_menu_item_xfn' => 
      array (
        0 => '',
      ),
      '_menu_item_url' => 
      array (
        0 => '',
      ),
    ),
    'terms' => 
    array (
      0 => 
      stdClass::__set_state(array(
         'term_id' => '105',
         'name' => 'Test 1',
         'slug' => 'test-1',
         'term_group' => '0',
         'term_taxonomy_id' => '106',
         'taxonomy' => 'nav_menu',
         'description' => '',
         'parent' => '0',
         'count' => '9',
      )),
    ),
  ),
  // … and so on. It is a long list.
share|improve this answer
    
Ah this looks great, I love debug output. I'll take a look at this soon and check back in, thanks! –  Jarrod Nov 1 '12 at 19:52
    
This is exactly the info I needed and helped me figure out the rest, thanks! And also, I'm not sure how you understood what I was asking, I re-read my question and it hardly even makes sense to me. –  Jarrod Nov 21 '12 at 15:05
add comment

Your Answer

 
discard

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.