Retrieve menu items hierarchically in WordPress

Home   »   Retrieve menu items hierarchically in WordPress

```php

/**
 * Get Menu Items From Location
 *
 * @param $location : location slug given as key in register_nav_menus
 */

function getMenuItemsFromLocation($location) {
	$theme_locations = get_nav_menu_locations();
	$menu_obj = get_term( $theme_locations[$location], 'nav_menu' );
	return is_wp_error($menu_obj) ? [] : getMenuItemsForParent($menu_obj->slug, 0)
}


/**
 * Get Menu Items For Parent
 * 
 * @param $menuSlug : menu slug for the CMS entry (not the key in register_nav_menus)
 * @param $parentId
 * @return array of items formatted as objects with : name / url / children (fetched recursively)
 */

function getMenuItemsForParent($menuSlug, $parentId) {
	$args = [
			'post_type' => 'nav_menu_item',
			'meta_key' => '_menu_item_menu_item_parent',
			'meta_value' => $parentId,
			'tax_query' => [
				[
					'taxonomy' => 'nav_menu',
					'field' => 'slug',
					'terms' => [$menuSlug]
				]
			],
			'order' => 'ASC',
			'orderby' => 'menu_order',
			'posts_per_page' => -1
		];
	$tmpItems = query_posts($args);

	$items = [];
	foreach ( $tmpItems as $tmpItem ) {
		$item = new stdClass;
		$type = get_post_meta($tmpItem->ID, '_menu_item_type', true);
		switch($type):

			case 'post_type':
				$postId = get_post_meta($tmpItem->ID, '_menu_item_object_id', true);
				$post = get_post($postId);
				$item->name = $post->post_title;
				$item->url = '/'.$post->post_type.'/'.$post->post_name;
				break;

			case 'custom':
				$item->name = $tmpItem->post_title;
				$item->url = get_post_meta($tmpItem->ID, '_menu_item_url', true);
				
			// note : this has to be completed with every '_menu_item_type' (could also come from plugin)

		endswitch;
		$item->children = getMenuItemsForParent($menuSlug, $tmpItem->ID);
		$items[] = $item;
	}

	return $items;
}

/**
 * Usage
 */
 
$menuItems = getMenuItemsFromLocation('footer_menu');

// will return :
[
	'name' => 'Menu item 1'
	'url' => '/my-post-type/my-url-1'
	'children' => [
		'name' => 'Menu item 2'
		'url' => '/external-custom-link'
		'children' => []
	],
	// etc...
]
```

Leave a Reply

Your email address will not be published.