How to display comments in a nested way with parent id

I have a comments table that looks like this: the contents of the layout are also added:

 +------------+---------+----------+-------------------+------------------------------------+---------------------------+ | comment_id | user_id | movie_id | comment_parent_id | comment_content | comment_creation_datetime | +------------+---------+----------+-------------------+------------------------------------+---------------------------+ | 26 | 1 | 16329 | 0 | Första | 2016-01-24 10:42:49 | | 27 | 1 | 16329 | 26 | Svar till första | 2016-01-24 10:42:55 | | 28 | 1 | 16329 | 26 | Andra svar till förta | 2016-01-24 10:43:06 | | 29 | 1 | 16329 | 28 | Svar till "andra svar till första" | 2016-01-24 10:43:23 | +------------+---------+----------+-------------------+------------------------------------+---------------------------+ 

Im trying to display Reddit style comments like this image:

enter image description here

Im trying to get all comments SELECT * FROM comments WHERE movie_id = :movie_id ORDER BY comment_creation_datetime DESC and then recursively log them out.

I tried a bunch of foreach loops but nobody works as expected

 foreach($this->comments as $value){ ?> <div class="comment"> Comment content <?php echo $value->comment_content; ?> <?php if($value->comment_parent_id > 0){ foreach($value as $sub_comment){ ?> <div class="comment"> comment comment on comment: <?php echo $value->comment_content; ?> </div> <?php }} ?> </div> <?php } 

My question is:

How to undo comments in a nested Reddit style using a foreach loop?

+5
source share
3 answers

I would use some recursive function, you start with parent_id == 0 and recursively print all those who are their direct children.

This code is not tested, but you can get this idea:

 function printComment($comment, $comments) { foreach($comments as $c) { if($c->parent_id == $comment->comment_id) { $output .= "<li>".printCommment($c)."</li>"; } } $output = "<ul>".$comment->comment_content."</ul>".$output; return $output; } foreach($this->comments as $comment) { if($comment->parent_id == 0) { echo printComment($comment,$this->comments); } } 
+1
source

Working with an adjacency list model can be more problematic with SQL. You need to get all rows with a single query and save the link of any parent to the search table.

 $sth = $pdo->prepare("SELECT * FROM comments WHERE movie_id = ? ORDER BY comment_creation_datetime DESC"); $sth->execute([$movie_id]); $comments = $sth->fetchAll(PDO::FETCH_ASSOC); $lookup_table = []; foreach ($comments as $comment_key => $comment) { $lookup_table[$comment['comment_parent_id']][$comment_key] = $comment['comment_id']; } 

Now you can display them with

 function recursive_child_display($comments, $lookup_table, $root = 0, $deep = 0) { if (isset($lookup_table[$root])) { foreach ($lookup_table[$root] as $comment_key => $comment_id) { // You can use $deep to test if you're in a comment of a comment echo '<div class="comment">'; echo 'Comment content ', $comments[$comment_key]['comment_content']; recursive_child_display($comments, $lookup_table, $comment_id, $deep+1); echo '</div>'; } } } 

Example:

 // display all the comments from the root recursive_child_display($comments, $lookup_table, 0); 

 // display all comments that are parent of comment_id 26 recursive_child_display($comments, $lookup_table, 26); 
+1
source

You need to make a list of root comments and hierarchically organize them all. You can do this in one go:

 $roots = []; $all = []; foreach($comments as $comment) { // Make sure all have a list of children $comment->comments = []; // Store all by ID in associative array $all[$comment->comment_id] = $comment; // Store the root comments in the roots array, and the others in their parent if(empty($comment->comment_parent_id)) $roots[] = $comment; else $all[$comment->comment_parent_id]->comments[] = $comment; } // Check it all done correctly! print_r($roots); 

You saved the list by the date that was saved in this approach. In addition, since you just reorganized by reference, it is lightning fast and ready for use in engine templates or something else - you do not need to print inline, like other answers.

+1
source

Source: https://habr.com/ru/post/1241351/


All Articles