0

I have a task where I must to get hierarchy tree from given array. An arrays inside array looks:

$commentsArray = [
    [1, 1, 'Comment 1'],
    [2, 1, 'Comment 2'],
    [3, 2, 'Comment 3'],
    [4, 1, 'Comment 4'],
    [5, 2, 'Comment 5'],
    [6, 3, 'Comment 6'],
    [7, 7, 'Comment 7'],
];

now I need to get output into html like:

Comment 1
-- Comment 2
----Comment 3 
------Comment 6
----Comment 5
--Comment 4
Comment 7  

My code doesn't work:

<?php

$commentsArray = array(
    array(
        'id' => 1,
        'parent_id' => 1,
        'content' => 'Comment 1'
    ),
    array(
        'id' => 2,
        'parent_id' => 1,
        'content' => 'Comment 2'
    ),
    array(
        'id' => 3,
        'parent_id' => 2,
        'content' => 'Comment 3'
    ),
   ...
);

$new = array();

foreach ($commentsArray as $comment){
    $new[$comment['parent_id']][] = $comment;
}

$tree = createTree($new, array($commentsArray[0]));

echo '<pre>';
print_r($tree);
echo '</pre>';

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;
}

I tried to run script without first element of $commentsArray and it works but I need the first element

1

3 Answers 3

1

You could use two functions:

  • One to iteratively create the hierarchy structure.
  • One to recursively create HTML for that hierarchy.
function createForest(&$list) {
    $bykey = [0 => ["children" => []]];
    foreach ($list as [$id, $parentid, $comment]) {
        $bykey[$id] = ["comment" => $comment, "children" => []];
        $bykey[$parentid == $id ? 0 : $parentid]["children"][] = &$bykey[$id];
    }
    return $bykey[0]["children"];
}

function createHtml(&$forest) {
    $html = "";
    foreach ($forest as ["comment" => $comment, "children" => $children]) {
        $html .= "<li>$comment" . createHtml($children) . "</li>";
    }
    return $html ? "<ul>$html</ul>" : "";
}

$commentsArray = [
    [1, 1, 'Comment 1'],
    [2, 1, 'Comment 2'],
    [3, 2, 'Comment 3'],
    [4, 1, 'Comment 4'],
    [5, 2, 'Comment 5'],
    [6, 3, 'Comment 6'],
    [7, 7, 'Comment 7'],
];
$forest = createForest($commentsArray);
$html = createHtml($forest);
echo $html;

Output:

enter image description here

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

Comments

0
<?php

$comments = [
    [1, 1, 'Comment 1'],
    [2, 1, 'Comment 2'],
    [3, 2, 'Comment 3'],
    [4, 1, 'Comment 4'],
    [5, 2, 'Comment 5'],
    [6, 3, 'Comment 6'],
    [7, 7, 'Comment 7'],
];

$map = [];

foreach($comments as $c) {
    $id = $c[0] === $c[1] ? 0 : $c[1];
    $map[$id][] = $c;
}

function print_comments($arr, $depth) {
    global $map;
    foreach($arr as $c) {
        echo str_repeat("--", $depth) . "{$c[2]}\n";
        print_comments($map[$c[0]] ?? [], $depth+1);
    }
}

print_comments($map[0], 0);

1 Comment

Produces the output OP is looking for (3v4l.org/CAApZ). Your answer would be more valuable if you explained how the solution works.
0

I did it myself. But Thanks anyway!

<?php

class CommentService
{
/**
 * @param array $commentsArray
 *
 * @return string
 */
public function getHierarchyTreeDOM(array $commentsArray): string
{
    $processedIds = [];

    $htmlDOM = '<ul>';

    foreach ($commentsArray as $comment) {

        if ($comment[0] === $comment[1]) {
            $htmlDOM .= '<li>' . $comment[2];
            $htmlDOM .= $this->buildHierarchyRecursively($commentsArray, $comment[0], $processedIds);
            $htmlDOM .= '</li>';
        }

    }

    return $htmlDOM . '</ul>';
}

/**
 * @param array $commentsArray
 * @param int $parentId
 * @param array $processedIds
 *
 * @return string
 */
private function buildHierarchyRecursively(array $commentsArray, int $parentId = 1, array &$processedIds = []): string
{
    $htmlDOM = '<ul>';

    foreach ($commentsArray as $item) {

        if ($item[0] !== $parentId && $item[1] === $parentId && !in_array($item[0], $processedIds)) {
            $processedIds[] = $item[0];

            $htmlDOM .= '<li>' . $item[2];
            $htmlDOM .= $this->buildHierarchyRecursively($commentsArray, $item[0], $processedIds);
            $htmlDOM .= '</li>';
        }

    }

    return $htmlDOM . '</ul>';
}

}

Then in html page:

<?php

require_once('CommentService.php');

$commentService = new CommentService();

$commentsArray = [
    [1, 1, 'Comment 1'],
    [2, 1, 'Comment 2'],
    [3, 2, 'Comment 3'],
    [4, 1, 'Comment 4'],
    [5, 2, 'Comment 5'],
    [6, 3, 'Comment 6'],
    [7, 7, 'Comment 7'],
];

?>
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
      content="width=device-width, user-scalable=no, initial-scale=1.0, 
maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Comments</title>
</head>
<body>
    <h2>Comments:</h2>
    <?php

        echo $commentService->getHierarchyTreeDOM($commentsArray);

    ?>
</body>
</html>

Comments

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.