1

I'm trying to get a multidimensional array comparing the [id] values with the [parent_id] values from an array like this:

Array
(
    [0] => Array
        (
            [id] => 101
            [title] => parent_101
            [parent_id] => 0
            [level] => 1

        )

    [1] => Array
        (
            [id] => 118
            [title] => parent_118
            [parent_id] => 0
            [level] => 1

        )

    [2] => Array
        (
            [id] => 119
            [title] => child_119
            [parent_id] => 118
            [level] => 2
        )

    [4] => Array
        (
            [id] => 173
            [title] => subchild_173
            [parent_id] => 119
            [level] => 3

        )

    [5] => Array
        (
            [id] => 120
            [title] => child_120
            [parent_id] => 118
            [level] => 2
        )

    [6] => Array
        (
            [id] => 145
            [title] => deeperchild_145
            [parent_id] => 173
            [level] => 4
        )

)

The result should be a new array like this:

Array
(
    [0] => Array
        (
            [title] => parent_101
            [id] => 101
            [parent_id] => 1
            [level] => 1
            [childrens] => Array
                (
                )

        )

    [1] => Array
        (
            [id] => 118
            [title] => parent_118
            [parent_id] => 1
            [level] => 1
            [childrens] => Array
                (
                    [0] => Array
                        (
                            [id] => 119
                            [title] => child_119
                            [parent_id] => 118
                            [level] => 2
                            [deeper] => Array
                                (
                                    [0] => Array
                                        (
                                            [id] => 173
                                            [title] => subchild_173
                                            [parent_id] => 119
                                            [level] => 3
                                            [deeperchild] => Array
                                                (
                                                    [id] => 145
                                                    [title] => deeperchild_145
                                                    [parent_id] => 173
                                                    [level] => 4
                                                )
                                        )

                                )

                        )

                    [1] => Array
                        (
                            [id] => 120
                            [title] => parent_120
                            [parent_id] => 118
                            [level] => 2
                            [deeper] => Array
                                 (
                                 )                      
                       )
                )
        )
)

so far I come up with this code but I'm stuck at the 3rd level deeper and I was wondering if there is a better way to do that.

> $parentsitms = array(); $deeperArr  = array(); $childsArr = array();
> $childparent = array(); $menu = array();
> 
> foreach ($list as $items) {
> 
>     if($items->level==='1'):
>         $idparent =  $items->id; 
>         $parents = $items->title; 
>         $parentsitms[] = ['id'=>$items->id,'title'=>$items->title,'parent_id'=>$items->parent_id,'level'=>$items->level];  
> 
>     endif;
> 
> }
>             foreach ($parentsitms as $menuitm) {
>                 $parents = $menuitm;
> 
>                 foreach($list as $chd){
>                     
>                         if($menuitm['id'] === $chd->parent_id):
>                             $childparent = $chd->id;
>                             $childsItms = ['id'=>$chd->id,'title'=>$chd->title,'parent_id'=>$chd->parent_id,'level'=>$chd->level];
>                             $childsArr[] = [array_merge($childsItms,array('deeper'=>array()))];
>                         endif;
> 
>                         if($childparent === $chd->parent_id):
>                             $array =  ['title'=>$chd->title,'id'=>$chd->id,'parent_id'=>$chd->parent_id,'level'=>$chd->level];
>                             $deeperArr[] = ['id'=>$chd->id,'title'=>$chd->title,'parent_id'=>$chd->parent_id,'level'=>$chd->level];
>                             $childsArr  = [array_merge($childsItms,array('deeper'=>$deeperArr))];
>                         endif;
> 
>                         ######## can't get the 4th level deeper ######
> 
>                         
>                  }
> 
>                     $menu[] = array_merge($parents,array('childrens'=>$childsArr));
>             }
> 
>             echo '<pre>'; print_r($menu);

Any help is very appreciated.

1
  • 3
    Please get rid of all the > prefixes in the code, they make it impossible to execute. Commented Dec 18, 2019 at 18:12

1 Answer 1

1

This code uses a non-recursive method which is a more common method of solving this type of problem. I prefer this method as it makes just one pass through the data and can be easier to follow through (IMHO).

I've added comments to the code as it's easier to describe with the code. The only thing I would say is that this always uses children as the name of the child elements and not the way you do this at the moment...

// Order array so that they are in order of level
usort($list, function ( $a, $b ) { return $a['level'] <=> $b['level']; });

// Create start point with all of the items indexed by their ID
$output = array_column($list, null, "id");

// Work in reverse order
foreach ( array_reverse(array_column($list, "id")) as $id ) {
    $parent = $output[$id]['parent_id'];
    // If there is a parent to work with 
    if ( $parent != 0 )   {
        // Ensure that the add point is there
        if ( !isset($output[$parent]['children']) )  {
            $output[$parent]['children'] = [];
        }
        // Prepend the new item to the list (do this as the items
        // are added in reverse oder)
        array_unshift($output[$parent]['children'], $output[$id]);
        // Remove the old node from the base list
        unset($output[$id]);
    }
}

$output = array_values($output);
print_r($output);

gives...

Array
(
    [0] => Array
        (
            [id] => 101
            [title] => parent_101
            [parent_id] => 0
            [level] => 1
        )

    [1] => Array
        (
            [id] => 118
            [title] => parent_118
            [parent_id] => 0
            [level] => 1
            [children] => Array
                (
                    [0] => Array
                        (
                            [id] => 119
                            [title] => child_119
                            [parent_id] => 118
                            [level] => 2
                            [children] => Array
                                (
                                    [0] => Array
                                        (
                                            [id] => 173
                                            [title] => subchild_173
                                            [parent_id] => 119
                                            [level] => 3
                                            [children] => Array
                                                (
                                                    [0] => Array
                                                        (
                                                            [id] => 145
                                                            [title] => deeperchild_145
                                                            [parent_id] => 173
                                                            [level] => 4
                                                        )

                                                )

                                        )

                                )

                        )

                    [1] => Array
                        (
                            [id] => 120
                            [title] => child_120
                            [parent_id] => 118
                            [level] => 2
                        )

                )

        )

)
Sign up to request clarification or add additional context in comments.

1 Comment

Nice, thanks very much, it's exactly what I needed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.