我有一个表comments
,看起来像这样,还添加了一些模型内容:
+------------+---------+----------+-------------------+------------------------------------+---------------------------+
| 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 |
+------------+---------+----------+-------------------+------------------------------------+---------------------------+
我试图显示评论Reddit样式,如下图所示:
我试图获取所有评论SELECT * FROM comments WHERE movie_id = :movie_id ORDER BY comment_creation_datetime DESC
,然后递归回显它们。
我尝试了一堆foreach
循环,但没有一个按预期工作
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 }
如何使用foreach循环以嵌套的Reddit样式回显注释?
答案 0 :(得分:2)
我会使用一些递归函数,你从parent_id == 0
开始,并递归打印所有直接孩子。
此代码未经过测试,但您可以理解:
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 :(得分:2)
使用邻接列表模型对SQL来说可能更成问题。您需要使用单个查询检索所有行,并将任何父项子项的引用存储在查找表中。
$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'];
}
现在您可以使用
显示它们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>';
}
}
}
示例:
// 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);
答案 2 :(得分:2)
您需要制作根评论列表,并按层次结构组织所有评论。你可以一气呵成:
$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's all done correctly!
print_r($roots);
您按日期对列表进行了预先排序,这是在此方法中保留的。此外,由于您只是通过引用重新组织,这是快速闪电,并准备用于模板引擎或任何东西 - 无需像其他答案那样打印内联。