Get page IDs from nav items

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?

Related posts

Leave a Reply

2 comments

  1. 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 );

  2. 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
    ) );