3

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.

1 Answer 1

4
  • 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.
2
  • Ah this looks great, I love debug output. I'll take a look at this soon and check back in, thanks!
    – Jarrod
    Commented Nov 1, 2012 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
    Commented Nov 21, 2012 at 15:05

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.