wp_get_nav_menu_items()WP 3.0.0

Gets the navigation menu items as an array.

By passing a menu name, ID or slug, the function will retrieve the navigation menu items.

Returns all elements (links) of the specified navigation menu, which is created in the admin-panel: Appearance > Menu.

Note: Most arguments passed to the $args parameter – save for 'output_key' – are specifically for retrieving nav_menu_item posts from get_posts() and may only indirectly affect the ultimate ordering and content of the resulting nav menu items that get returned from this function.

1 time — 0.015463 sec (extremely slow) | 50000 times — 124.89 sec (extremely slow) | PHP 7.1.2, WP 4.7.3
Hooks from the function

Return

Array|false. Array of menu items, otherwise false.

Usage Template

$items = wp_get_nav_menu_items( 5, [
	'output_key'  => 'menu_order',
] );

Usage

wp_get_nav_menu_items( $menu, $args );
$menu(int|string|WP_Term) (required)

Menu ID, slug, name, or WP_Term object.

The identifier that is set during menu registration (menu location) does not work here.

$args(array)

Arguments to pass to get_posts().

Default: array() - presets

  • order(string)
    How to order nav menu items: ASC or DESC. Will be ignored if 'output' is ARRAY_A.
    Default: 'ASC'

  • orderby(string)
    Field to order menu items by as retrieved from get_posts().
    An additional field by which to sort can also be specified in the output_key parameter. See the $output_key parameter for details.
    Default: 'menu_order'

  • output(string)
    In what form do you want to get the items.

    If ARRAY_A then to each menu item (object) one more property (sorting field) is added. The name of the added property is specified in the $output_key parameter. The value of the new property will be a number - the sequence number of the menu item. Also the menu items will be sorted using wp_list_sort() function by $output_key field with ASC direction.

    In other words, with ARRAY_A, the menu items are sorted separately, via wp_list_sort(), by the $output_key field with ASC direction. And the sequence number of the menu item is added to the each item object in the new property $item->$output_key.

    Default: ARRAY_A

  • output_key(string)
    Key to use for ordering the menu items that get returned.

    Note that that is not a get_posts() argument and will only affect output of menu items processed in this function.

    Default: 'menu_order'

  • post_type(string)
    Menu items post type.
    Default: 'nav_menu_item'

  • post_status(string)
    Menu items post status.
    Default: 'publish'

  • nopaging(true|false)
    Whether to retrieve all menu items (true) or paginate (false).
    Default: true

Examples

0

#1 An example of building a simple menu list

// Get the menu items based on the $menu_name parameter
// (the same as 'theme_location' or 'menu' in the wp_nav_menu arguments)
// This code is the basis of the wp_nav_menu() function, where menu ID gets from slug

$menu_name = 'custom_menu_slug';
$locations = get_nav_menu_locations();

if( $locations && isset( $locations[ $menu_name ] ) ){

	// get menu items
	$menu_items = wp_get_nav_menu_items( $locations[ $menu_name ] );

	// create a list
	$menu_list = '<ul id="menu-' . $menu_name . '">';

	foreach ( (array) $menu_items as $key => $menu_item ){
		$menu_list .= '<li><a href="' . $menu_item->url . '">' . $menu_item->title . '</a></li>';
	}

	$menu_list .= '</ul>';
}
else {
	$menu_list = '<ul><li>Menu "' . $menu_name . '" undefined.</li></ul>';
}
0

#2 What data the returned object contains

It doesn't matter which link is added to the menu in the admin: a post, a taxonomy or an custom link. All of them are stored in 'wp_posts' table with the same fields (menu fields).

Many of the fields are simply unnecessary and do not make sense, because they relate to posts. Use the last values starting with 'db_id' they related to menu item.

$items = wp_get_nav_menu_items( 654 );

print_r( $items );

/* will output:
Array
(
	[1] => WP_Post Object
		(
			// it is the fields of the post. use them is not good idea.
			[ID] => 6364
			[post_author] => 1
			[post_date] => 2015-12-06 12:20:18
			[post_date_gmt] => 2015-12-06 07:20:18
			[post_content] =>
			[post_title] => Custom link 2
			[post_excerpt] =>
			[post_status] => publish
			[comment_status] => closed
			[ping_status] => closed
			[post_password] =>
			[post_name] => custom-link-2
			[to_ping] =>
			[pinged] =>
			[post_modified] => 2015-12-06 12:20:18
			[post_modified_gmt] => 2015-12-06 07:20:18
			[post_content_filtered] =>
			[post_parent] => 0
			[guid] => http://wp-kama.com/id_6364/proizvolnaya-ssylka-2.html
			[menu_order] => 4
			[post_type] => nav_menu_item
			[post_mime_type] =>
			[comment_count] => 0
			[filter] => raw

			// these are menu fields, use them
			[db_id] => 6364
			[menu_item_parent] => 0
			[object_id] => 6364
			[object] => custom
			[type] => custom
			[type_label] => Custom link
			[title] => Custom link 2
			[url] => http://example.com/foo
			[target] =>
			[attr_title] =>
			[description] =>
			[classes] => Array
				(
					[0] =>
				)

			[xfn] =>
		)
	[1] => WP_Post Object
		(
		...
		)

)

*/
0

#3 Building bootstrap 3 menu with submenu items

Without use WP_Nav_Walker (boostrap)! (Require bootstrap.css and bootstrap.js).

<?php
// Intented to use bootstrap 3.
// Location is like a 'primary'
// After, you print menu just add create_bootstrap_menu("primary") in your preferred position;

#add this function in your theme functions.php

function create_bootstrap_menu( $theme_location ) {
	if ( ($theme_location) && ($locations = get_nav_menu_locations()) && isset($locations[$theme_location]) ) {

		$menu_list  = '<nav class="navbar navbar-default">' ."\n";
		$menu_list .= '<div class="container-fluid">' ."\n";
		$menu_list .= '<!-- Brand and toggle get grouped for better mobile display -->' ."\n";
		$menu_list .= '<div class="navbar-header">' ."\n";
		$menu_list .= '<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">' ."\n";
		$menu_list .= '<span class="sr-only">Toggle navigation</span>' ."\n";
		$menu_list .= '<span class="icon-bar"></span>' ."\n";
		$menu_list .= '<span class="icon-bar"></span>' ."\n";
		$menu_list .= '<span class="icon-bar"></span>' ."\n";
		$menu_list .= '</button>' ."\n";
		$menu_list .= '<a class="navbar-brand" href="' . home_url() . '">' . get_bloginfo( 'name' ) . '</a>';
		$menu_list .= '</div>' ."\n";

		$menu_list .= '<!-- Collect the nav links, forms, and other content for toggling -->';

		$menu = get_term( $locations[$theme_location], 'nav_menu' );
		$menu_items = wp_get_nav_menu_items($menu->term_id);

		$menu_list .= '<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">' ."\n";
		$menu_list .= '<ul class="nav navbar-nav">' ."\n";

		foreach( $menu_items as $menu_item ) {
			if( $menu_item->menu_item_parent == 0 ) {

				$parent = $menu_item->ID;

				$menu_array = array();
				foreach( $menu_items as $submenu ) {
					if( $submenu->menu_item_parent == $parent ) {
						$bool = true;
						$menu_array[] = '<li><a href="' . $submenu->url . '">' . $submenu->title . '</a></li>' ."\n";
					}
				}
				if( $bool == true && count( $menu_array ) > 0 ) {

					$menu_list .= '<li class="dropdown">' ."\n";
					$menu_list .= '<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">' . $menu_item->title . ' <span class="caret"></span></a>' ."\n";

					$menu_list .= '<ul class="dropdown-menu">' ."\n";
					$menu_list .= implode( "\n", $menu_array );
					$menu_list .= '</ul>' ."\n";

				} else {

					$menu_list .= '<li>' ."\n";
					$menu_list .= '<a href="' . $menu_item->url . '">' . $menu_item->title . '</a>' ."\n";
				}

			}

			// end <li>
			$menu_list .= '</li>' ."\n";
		}

		$menu_list .= '</ul>' ."\n";
		$menu_list .= '</div>' ."\n";
		$menu_list .= '</div><!-- /.container-fluid -->' ."\n";
		$menu_list .= '</nav>' ."\n";

	} else {
		$menu_list = '<!-- no menu defined in location "'.$theme_location.'" -->';
	}

	echo $menu_list;
}
?>
0

#4 Building menu list with children (submenus)

And selecting the menu by it’s location:

// Intented to use with locations, like 'primary'
// clean_custom_menu("primary");

#add in your theme functions.php file

function clean_custom_menu( $theme_location ) {
	if ( ($theme_location) && ($locations = get_nav_menu_locations()) && isset($locations[$theme_location]) ) {
		$menu = get_term( $locations[$theme_location], 'nav_menu' );
		$menu_items = wp_get_nav_menu_items($menu->term_id);

		$menu_list  = '<nav>' ."\n";
		$menu_list .= '<ul class="main-nav">' ."\n";

		$count = 0;
		$submenu = false;

		foreach( $menu_items as $menu_item ) {

			$link = $menu_item->url;
			$title = $menu_item->title;

			if ( !$menu_item->menu_item_parent ) {
				$parent_id = $menu_item->ID;

				$menu_list .= '<li class="item">' ."\n";
				$menu_list .= '<a href="'.$link.'" class="title">'.$title.'</a>' ."\n";
			}

			if ( $parent_id == $menu_item->menu_item_parent ) {

				if ( !$submenu ) {
					$submenu = true;
					$menu_list .= '<ul class="sub-menu">' ."\n";
				}

				$menu_list .= '<li class="item">' ."\n";
				$menu_list .= '<a href="'.$link.'" class="title">'.$title.'</a>' ."\n";
				$menu_list .= '</li>' ."\n";

				if ( $menu_items[ $count + 1 ]->menu_item_parent != $parent_id && $submenu ){
					$menu_list .= '</ul>' ."\n";
					$submenu = false;
				}

			}

			if ( $menu_items[ $count + 1 ]->menu_item_parent != $parent_id ) {
				$menu_list .= '</li>' ."\n";
				$submenu = false;
			}

			$count++;
		}

		$menu_list .= '</ul>' ."\n";
		$menu_list .= '</nav>' ."\n";

	} else {
		$menu_list = '<!-- no menu defined in location "'.$theme_location.'" -->';
	}
	echo $menu_list;
}
0

#5 Get simple array of menu

function wp_get_menu_array($current_menu) {

	$array_menu = wp_get_nav_menu_items($current_menu);

	$menu = array();

	foreach ($array_menu as $m) {
		if (empty($m->menu_item_parent)) {
			$menu[$m->ID] = array();
			$menu[$m->ID]['ID']      =   $m->ID;
			$menu[$m->ID]['title']       =   $m->title;
			$menu[$m->ID]['url']         =   $m->url;
			$menu[$m->ID]['children']    =   array();
		}
	}

	$submenu = array();

	foreach ($array_menu as $m) {
		if ($m->menu_item_parent) {
			$submenu[$m->ID] = array();
			$submenu[$m->ID]['ID']       =   $m->ID;
			$submenu[$m->ID]['title']    =   $m->title;
			$submenu[$m->ID]['url']  =   $m->url;
			$menu[$m->menu_item_parent]['children'][$m->ID] = $submenu[$m->ID];
		}
	}

	return $menu;

}

Changelog

Since 3.0.0 Introduced.

Code of wp_get_nav_menu_items() WP 6.0

function wp_get_nav_menu_items( $menu, $args = array() ) {
	$menu = wp_get_nav_menu_object( $menu );

	if ( ! $menu ) {
		return false;
	}

	static $fetched = array();

	if ( ! taxonomy_exists( 'nav_menu' ) ) {
		return false;
	}

	$defaults = array(
		'order'       => 'ASC',
		'orderby'     => 'menu_order',
		'post_type'   => 'nav_menu_item',
		'post_status' => 'publish',
		'output'      => ARRAY_A,
		'output_key'  => 'menu_order',
		'nopaging'    => true,
		'tax_query'   => array(
			array(
				'taxonomy' => 'nav_menu',
				'field'    => 'term_taxonomy_id',
				'terms'    => $menu->term_taxonomy_id,
			),
		),
	);
	$args     = wp_parse_args( $args, $defaults );
	if ( $menu->count > 0 ) {
		$items = get_posts( $args );
	} else {
		$items = array();
	}

	// Prime posts and terms caches.
	if ( empty( $fetched[ $menu->term_id ] ) ) {
		$fetched[ $menu->term_id ] = true;
		$post_ids                  = array();
		$term_ids                  = array();
		foreach ( $items as $item ) {
			$object_id = get_post_meta( $item->ID, '_menu_item_object_id', true );
			$type      = get_post_meta( $item->ID, '_menu_item_type', true );

			if ( 'post_type' === $type ) {
				$post_ids[] = (int) $object_id;
			} elseif ( 'taxonomy' === $type ) {
				$term_ids[] = (int) $object_id;
			}
		}

		if ( ! empty( $post_ids ) ) {
			_prime_post_caches( $post_ids, false );
		}
		unset( $post_ids );

		if ( ! empty( $term_ids ) ) {
			_prime_term_caches( $term_ids );
		}
		unset( $term_ids );
	}

	$items = array_map( 'wp_setup_nav_menu_item', $items );

	if ( ! is_admin() ) { // Remove invalid items only on front end.
		$items = array_filter( $items, '_is_valid_nav_menu_item' );
	}

	if ( ARRAY_A === $args['output'] ) {
		$items = wp_list_sort(
			$items,
			array(
				$args['output_key'] => 'ASC',
			)
		);

		$i = 1;

		foreach ( $items as $k => $item ) {
			$items[ $k ]->{$args['output_key']} = $i++;
		}
	}

	/**
	 * Filters the navigation menu items being returned.
	 *
	 * @since 3.0.0
	 *
	 * @param array  $items An array of menu item post objects.
	 * @param object $menu  The menu object.
	 * @param array  $args  An array of arguments used to retrieve menu item objects.
	 */
	return apply_filters( 'wp_get_nav_menu_items', $items, $menu, $args );
}