Get menu items as multidimensional array

There are times when we need to get menu items as a big multidimensional array so we can do some processing before finally displaying them. We can’t simply use wp_get_nav_menu_items() because it returns a flat array. The solution for this is pretty simple: use a custom walker.

/**
 * Nav menu walker
 */
class Bridge_Walker_Nav_Menu extends Walker_Nav_Menu {

	/**
	 * Prepare item
	 *
	 * @param  object $item  Menu Item.
	 * @param  array  $args  Arguments passed to walk().
	 * @param  int    $depth Item's depth.
	 * @return array
	 */
	protected function prepare_item( $item, $args, $depth ) {
		$title   = apply_filters( 'the_title', $item->title, $item->ID );
		$title   = apply_filters( 'nav_menu_item_title', $title, $item, $args, $depth );
		$classes = apply_filters( 'nav_menu_css_class', array_filter( $item->classes ), $item, $args, $depth );

		return array(
			'id'          => absint( $item->ID ),
			'order'       => (int) $item->menu_order,
			'parent'      => absint( $item->menu_item_parent ),
			'title'       => $title,
			'url'         => $item->url,
			'attr'        => $item->attr_title,
			'target'      => $item->target,
			'classes'     => $classes,
			'xfn'         => $item->xfn,
			'description' => $item->description,
			'object_id'   => absint( $item->object_id ),
			'object'      => $item->object,
			'type'        => $item->type,
			'type_label'  => $item->type_label,
			'children'    => array(),
		);
	}


	/**
	 * Traverse elements to create list from elements.
	 *
	 * This method should not be called directly, use the walk() method instead.
	 *
	 * @param object $element           Data object.
	 * @param array  $children_elements List of elements to continue traversing.
	 * @param int    $max_depth         Max depth to traverse.
	 * @param int    $depth             Depth of current element.
	 * @param array  $args              An array of arguments.
	 * @param array  $output            Passed by reference. Used to append additional content.
	 */
	public function display_element( $element, &$children_elements, $max_depth, $depth, $args, &$output ) {
		if ( ! $element ) {
			return;
		}

		$id_field = $this->db_fields['id'];
		$id       = $element->$id_field;
		$item     = $this->prepare_item( $element, $args, $depth );

		if ( ! empty( $children_elements[ $id ] ) ) {
			foreach ( $children_elements[ $id ] as $child ) {
				$this->display_element(
					$child,
					$children_elements,
					1,
					( $depth + 1 ),
					$args,
					$item['children']
				);
			}

			unset( $children_elements[ $id ] );
		}

		$output[] = $item;
	}
}

Example Usage:

$menu_id   = 2;
$max_depth = 0; // All level.
$walker    = new Bridge_Walker_Nav_Menu;
$items     = $walker->walk( wp_get_nav_menu_items( $menu_id ), $max_depth );
Get menu items as multidimensional array

Leave a Reply

Your email address will not be published. Required fields are marked *