1

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'];
});
Timothy
  • 4,198
  • 6
  • 49
  • 59
  • Possible duplicate of [create array tree from array list](https://stackoverflow.com/questions/4196157/create-array-tree-from-array-list) – trincot Jan 28 '18 at 21:59
  • I tried that example and it didn't work for me. Kindly do a test with my data first. – Timothy Jan 28 '18 at 22:01

1 Answers1

1

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;
}
trincot
  • 317,000
  • 35
  • 244
  • 286