13

I am trying to get all the IDs in my navigation and convert it to a string so that I can use it with wp_query to get the pages that are only listed in the nav. The code to get the IDs:

$menu_name = 'primary';

if ( ( $locations = get_nav_menu_locations() ) && isset( $locations[ $menu_name ] )) {
    $menu = wp_get_nav_menu_object( $locations[ $menu_name ] );
    $menu_items = wp_get_nav_menu_items($menu->term_id);
}

foreach ( $menu_items as $menu_item ) {
    $numbers[] = $menu_item->ID;
}

$number = implode(',',$numbers);

But it is returning the wrong numbers. When I go to the admin area and hover my mouse over the pages, the number that shows up in the address bar on the bottom of the screen doesn't match. What am I doing wrong?

2 Answers 2

15

Menu items are stored in the posts table with a post_type of nav_menu_item. So, what you are returning is the ID of the menu item itself, not what it points to.

The page/post ID that the menu item refers to is stored in the postmeta table, with a post_id that matches the menu item ID and meta_key = _menu_item_object_id. The easiest way to get the meta_value (ie the page being pointed to by the menu item) is to use something like this:

$numbers[] = get_post_meta( $menu_item->ID, '_menu_item_object_id', true );

3
  • It took me a while to get the code that I posted above to work. I have been trying to add your code in but I have not been able to get it to work. I took out the foreach loop and tried your line above but got nothing. How do I use your example?
    – Jamie
    Commented Apr 6, 2013 at 19:34
  • @Jamie Just replace your line: $numbers[] = $menu_item->ID; with the one in my answer.
    – anu
    Commented Apr 6, 2013 at 23:16
  • This works great thank you! Commented Mar 4, 2021 at 21:52
1

I wouldn't be able to tell you when this change happened but as of WordPress version 5.2.4 you can use object and object_id to retrieve the page ID. Here's how I would do this:

/**
 * The `0` is added as a default case.
 * In case our menu does not contain any pages this
 * will prevent our query from returning all pages
 */
$page_ids           = array( 0 );
$registered_menu    = 'my_registered_menu';
$locations          = get_nav_menu_locations();

if( ! empty( $locations ) && isset( $locations[ $registered_menu ] ) ) {

    $menu = wp_get_nav_menu_object( $locations[ $registered_menu ] );
    $menu_items = wp_get_nav_menu_items( $menu->term_id );

    if( ! empty( $menu_items ) ) {

        foreach( $menu_items as $item ) {

            // Only grab page IDs
            if( 'page' !== $item->object ) {
                continue;
            }

            $page_ids[] = $item->object_id;

        }

    }

}

$page_query = new WP_Query( array(
    'post_type'     => 'page',
    'post_status'   => 'publish',
    'no_found_rows' => true,
    'post__in'      => $page_ids,
    'posts_per_page'=> 100, // Large upper limit
) );
1
  • Interesting. Thank you
    – Jamie
    Commented Oct 16, 2019 at 1:16

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.