How to show child item under its parent item of an array in php

I have an array like this:

Array
(
    [0] => stdClass Object
        (
            [ID] => 1
            [menu_item_parent] => 0
            [title] => Home
            [url] => http://www.example.com/
        )

    [1] => stdClass Object
        (
            [ID] => 2
            [menu_item_parent] => 0
            [title] => Menu 2
            [url] => http://www.example.com/menu-2/
        )

    [2] => stdClass Object
        (
            [ID] => 3
            [menu_item_parent] => 2
            [title] => Sub Menu 1
            [url] => http://www.example.com/menu-2/sub-menu-1
            [target] => 
        )

    [3] => stdClass Object
        (
            [ID] => 4
            [menu_item_parent] => 0
            [title] => Menu 4
            [url] => http://www.example.com/menu-4/
            [target] => 

        )
)

Now you can see 3rd item of an array is child item of the second array item(see the column menu_item_parent).Now my question is how can i show this parent item with it’s child item using this array.Please help.

Related posts

Leave a Reply

6 comments

  1. Finally solve my problem with the help of @Matt.C given link.Thanks to @Matt.C. Here’s the solution:

    Firstly get the menu items as a flat array:

    <?php
    $menu_name = 'main_nav';
    $locations = get_nav_menu_locations();
    $menu = wp_get_nav_menu_object( $locations[ $menu_name ] );
    $menuitems = wp_get_nav_menu_items( $menu->term_id, array( 'order' => 'DESC' ) );
    ?>
    

    Then iterate over the array of the menu items:

    <nav>
    <ul class="main-nav">
        <?php
        $count = 0;
        $submenu = false;
    
        foreach( $menuitems as $item ):
            // get page id from using menu item object id
            $id = get_post_meta( $item->ID, '_menu_item_object_id', true );
            // set up a page object to retrieve page data
            $page = get_page( $id );
            $link = get_page_link( $id );
    
            // item does not have a parent so menu_item_parent equals 0 (false)
            if ( !$item->menu_item_parent ):
    
            // save this id for later comparison with sub-menu items
            $parent_id = $item->ID;
        ?>
    

    Write the first parent item <li>:

     <li class="item">
            <a href="<?php echo $link; ?>" class="title">
                <?php echo $page->post_title; ?>
            </a>
            <a href="<?php echo $link; ?>" class="desc">
                <?php echo $page->post_excerpt; ?>
            </a>
        <?php endif; ?>
    

    Check that this items’ parent id matches the stored parent id:

         <?php if ( $parent_id == $item->menu_item_parent ): ?>
    Start sub-menu <ul> and set $submenu flag to true for later referance:
    
                <?php if ( !$submenu ): $submenu = true; ?>
                <ul class="sub-menu">
                <?php endif; ?>
    Write the sub-menu item:
    
                    <li class="item">
                        <a href="<?php echo $link; ?>" class="title"><?php echo $page->post_title; ?></a>
                        <a href="<?php echo $link; ?>" class="desc"><?php echo $page->post_excerpt; ?></a>
    

    If the next item does not have the same parent id and we have a sub-menu declared then close the sub-menu <ul>

    <?php if ( $menuitems[ $count + 1 ]->menu_item_parent != $parent_id && $submenu ): ?>
            </ul>
            <?php $submenu = false; endif; ?>
    
    <?php endif; ?>
    

    Again, if the next item in the array does not have the same parent id close the <li>

      <?php if ( $menuitems[ $count + 1 ]->menu_item_parent != $parent_id ): ?>
        </li>                           
        <?php $submenu = false; endif; ?>
    
    <?php $count++; endforeach; ?>
      </ul>
    </nav> 
    
  2. Try this : I added the input as array, change to objects as per your question.

    $array  = Array( array("ID" => 1,"menu_item_parent" => 0,"title" => "Home","url" => "http://www.example.com/"),
                     array("ID" => 2,"menu_item_parent" => 0,"title" => "Menu 2","url" => "http://www.example.com/menu-2/"),
                     array("ID" => 3,"menu_item_parent" => 2,"title" => "Sub Menu 1","url" => "http://www.example.com/menu-2/sub-menu-1","target" =>"" ),
                     array("ID" => 4,"menu_item_parent" => 0,"title" => "Menu 4","url" => "http://www.example.com/menu-4/","target" => "")
              );
    
    $res   = array();         
    foreach($array as $val){
       if($val['menu_item_parent'] != 0){
           $res[$val['menu_item_parent']]['child'][] = $val;
       }
       else{
           $res[$val['ID']] = $val;
       }
    }
    
    echo "<pre>";
    print_r($res);
    

    Output:

    Array
    (
        [1] => Array
            (
                [ID] => 1
                [menu_item_parent] => 0
                [title] => Home
                [url] => http://www.example.com/
            )
    
        [2] => Array
            (
                [ID] => 2
                [menu_item_parent] => 0
                [title] => Menu 2
                [url] => http://www.example.com/menu-2/
                [child] => Array
                    (
                        [0] => Array
                            (
                                [ID] => 3
                                [menu_item_parent] => 2
                                [title] => Sub Menu 1
                                [url] => http://www.example.com/menu-2/sub-menu-1
                                [target] => 
                            )
    
                    )
    
            )
    
        [4] => Array
            (
                [ID] => 4
                [menu_item_parent] => 0
                [title] => Menu 4
                [url] => http://www.example.com/menu-4/
                [target] => 
            )
    
    )
    
  3. Here’s a very simple class for your WordPress-specific problem with a get_submenu function that returns all submenu items:

    class NestedMenu
    {
        private $flat_menu;
        public $items;
    
        function __construct($name)
        {
            $this->flat_menu = wp_get_nav_menu_items($name);
            $this->items = array();
            foreach ($this->flat_menu as $item) {
                if (!$item->menu_item_parent) {
                    array_push($this->items, $item);
                }
            }
        }
    
        public function get_submenu($item)
        {
            $submenu = array();
            foreach ($this->flat_menu as $subitem) {
                if ($subitem->menu_item_parent == $item->ID) {
                    array_push($submenu, $subitem);
                }
            }
            return $submenu;
        }
    }
    

    Usage. Construct an instance:

    $menu = new NestedMenu('menu_name');
    

    Iterate:

    foreach ($menu->items as $item) { ...
    

    And obtain the submenu inside the loop:

    $submenu = $menu->get_submenu($item);
    

    Before displaying the submenu, you can check if it exists:

    if ($submenu): ...
    
  4. You can iterate over the array and if the object has a parent add it to a children array of that parent. For example:

    $array = array(
    
      1 => (object) array('menu_item_parent' => 0),
      2 => (object) array('menu_item_parent' => 1),
      3 => (object) array('menu_item_parent' => 0),
    
    );
    
    foreach ($array as $key => $object)
    {
    
      if (0 != $object->menu_item_parent && isset($array[$object->menu_item_parent]))
      {
    
        if (!property_exists($array[$object->menu_item_parent], 'children'))
        {
            $array[$object->menu_item_parent]->children = array();
        }
    
        $array[$object->menu_item_parent]->children[] = $object;
    
        unset($array[$key]);    
    
      }
    
    }
    
    echo '<pre>' . print_r($array, TRUE) . '</pre>';
    

    Will convert:

    Array
    (
        [1] => stdClass Object
            (
                [menu_item_parent] => 0
            )
    
        [2] => stdClass Object
            (
                [menu_item_parent] => 1
            )
    
        [3] => stdClass Object
            (
                [menu_item_parent] => 0
            )
    
    )
    

    To:

    Array
    (
        [1] => stdClass Object
            (
                [menu_item_parent] => 0
                [children] => Array
                    (
                        [0] => stdClass Object
                            (
                                [menu_item_parent] => 1
                            )
    
                    )
    
            )
    
        [3] => stdClass Object
            (
                [menu_item_parent] => 0
            )
    
    )
    

    Then you can iterate over each object and show its children if needed:

    foreach ($array as $object)
    {
    
      echo 'Parent: ' . $object->title . '<br>';
    
      if (property_exists($object, 'children') && !empty($object->children))
      {
    
        echo '&nbsp;&nbsp;&nbsp;Children: ';
    
        foreach ($object->children as $child)
        {
          echo $child->title . '<br>';
        }
    
      }
    
    }
    
  5. Check using foreach function in php.
    like

    $array = array("apple" => 1, "orange" => 2);
    $sep = "";
    foreach($array as $key => $value) {
      if($sep) {
        $sep .= "<br/>key:".$key." / value:".$value;
      } else {
        $sep = "key:".$key." / value:".$value;
      }
    } 
    

    Output:

    key:apple / value:1
    key:orange / value:2
    
  6. This would be my solution. Moves the childs under the parent object into children and creates a boolean under the parent called has_child which value will be 1. Finally, unsets and removes the child from the main variable.

    $elements = wp_get_nav_menu_items("theme-location");
    
    foreach($elements as $index => $item)
    {
        if($item->menu_item_parent != 0)
        {
            foreach($elements as $index2 => $item2)
            {
                if($item2->ID == $item->menu_item_parent)
                {
                    $elements[$index2]->has_child = true;
    
                    if(!isset($elements[$index2]->children))
                    {
                        $elements[$index2]->children = array();
                    }
                    $elements[$index2]->children[] = $item;
                }
            }
            unset($elements[$index]);           
        }
    }