Timothy
Timothy

Reputation: 4285

Create an array tree from a multidimensional PHP array

I am trying to construct a hierarchy of comments so some have to be nested under each other.

The initial array is something like this:

$comments = [
    [   
        'id'=> 1, 
        'parent_id'=> null,
        'children'=> [],
    ],
    [   
        'id'=> 2, 
        'parent_id'=> null,
        'children'=> [],
    ],
    [   
        'id'=> 3, 
        'parent_id'=> null,
        'children'=> [],
    ],
    [   
        'id'=> 4, 
        'parent_id'=> 2,
        'children'=> [],
    ],
    [   
        'id'=> 5, 
        'parent_id'=> 3,
        'children'=> [],
    ],
    [   
        'id'=> 6, 
        'parent_id'=> 4,
        'children'=> [],
    ],
    [   
        'id'=> 7, 
        'parent_id'=> 4,
        'children'=> [],
    ],
];

The output for the above array should be something like this:

$comments = [
    [   
        'id'=> 1, 
        'parent_id'=> null,
        'children'=> [],
    ],
    [   
        'id'=> 2, 
        'parent_id'=> null,
        'children'=> [
            [   
                'id'=> 4, 
                'parent_id'=> 2,
                'children'=> [
                    [   
                        'id'=> 6, 
                        'parent_id'=> 4,
                        'children'=> [],
                    ],
                    [   
                        'id'=> 7, 
                        'parent_id'=> 4,
                        'children'=> [],
                    ],
                ],
            ],
        ],
    ],
    [   
        'id'=> 3, 
        'parent_id'=> null,
        'children'=> [
            [   
                'id'=> 5, 
                'parent_id'=> 3,
                'children'=> [],
            ],
        ],
    ],
];

My code below gets the top part right but misses the second level children:

// organize comments into a hierarchy
$tree = array_map(function($comment) use ($comments) {
    $children = [];
    $comments = array_map(function($child) use ($comment, &$children) {
        // return [$child['parent_id'], $comment['id']];
        if($child['parent_id'] == $comment['id']){
            $children[] = $child;
        }
        return $child;
    }, $comments);
    $comment['children'] = $children;
    return $comment;
}, $comments);

// remove children from the top
return $comments = array_filter($tree, function($child) {
    return !$child['parent_id'];
});

Upvotes: 1

Views: 89

Answers (1)

trincot
trincot

Reputation: 350252

You can use the code posted in this answer (so really this question is a duplicate), but obviously you have to take note of the differences:

  • Your input variable name is different
  • The parent property name is slightly different
  • The root nodes have value null as opposed to 0 in the referenced answer

Because of the last point you must pass $new[null] as second argument to createTree.

Here is the code adapted to your variable names and the above comment taken into account:

$new = array();
foreach ($comments as $a){
    $new[$a['parent_id']][] = $a;
}   
$tree = createTree($new, $new[null]);
print_r($tree);

function createTree(&$list, $parent){
    $tree = array();
    foreach ($parent as $k=>$l){
        if(isset($list[$l['id']])){
            $l['children'] = createTree($list, $list[$l['id']]);
        }
        $tree[] = $l;
    } 
    return $tree;
}

Upvotes: 1

Related Questions