所以我使用的php框架是Laravel。我有一个注释表,并且允许注释包含子注释。我在更新时间前订购了评论:
$post->comments()->orderBy('updated_at')->paginate(10);
现在我想对评论进行分组,以便将具有相同父评论的所有子评论放在一起,即父评论,然后是其所有子评论一个接一个,然后是下一个父评论,再是其所有个子评论一个又一个,等等。如下所示:
- 注释1
- 注释1的子注释A
- 注释1的子注释B
- 注释2
- 注释2的子注释C
- 注释2的子注释D
- 子注释D的子注释E
现在这个订单不能用简单的"orderBy"来完成,我的问题是:我可以用Laravel查询生成器/雄辩器来完成吗,还是必须手动订购?顺便说一句,我已经设置了Comment模型,这样它的父级/子级就可以通过以下方式获取:
$comment->parentComment;
$comment->childComments;
您可以使用模型关系(self)来实现这一点,例如,假设这是您的comments
表:
id (PK) | content | post_id | user_id | comment_parent
------------------------------------------------------
1 | Hello | 1 | 1 | 0 <-- This is a parent because of 0
2 | Hi | 1 | 2 | 1 <-- child of 1
3 | Howdy | 1 | 3 | 1 <-- child of 1
将该表读取为:共有三个注释,第一个注释由User
和user_id-1
生成,它有两个子注释由另外两个用户生成,它们的id
是user_id-2
和user_id-3
。
这里,comment_parent
列保持parent
和child
注释之间的关系。值为0
的comment_parent
是父评论,并且除了0
之外,例如,这里两个评论具有1
的comment_parent
,这意味着这两个评论是id/PK
为1
的评论的子评论。
因此,现在,在您的Comment
模型中声明以下方法:
// Get only children of a comment
public function children()
{
return $this->hasMany('Comment', 'comment_parent');
}
// Get the user of comment
public function user()
{
return $this->belongsTo('User', 'user_id');
}
// Get the post of comment
public function post()
{
return $this->belongsTo('Post', 'post_id');
}
然后在您的Post
模型中声明此方法:
// Only parent comments
public function comments()
{
return $this->hasMany('Comment', 'post_id')->where('comment_parent', 0);
}
// All Comments
public function allComments()
{
return $this->hasMany('Comment', 'post_id');
}
现在,如果你做这样的事情:
$post = Post::with('comments.children')->find(1);
然后你可以在你的视野中尝试这样的东西(可能在你的post.single.blade.php
中):
{{ $post->title }}
{{ $post->body }}
<!-- Comment Template For Posting New Comments-->
@if($post->comments->count())
@foreach($post->comments as $comment)
{{ $comment->user->username }}
{{ $comment->body }}
@if($comment->children->count())
@foreach($comment->children as $childComment)
{{ $childComment->user->username }}
{{ $childComment->body }}
@endforeach
@endif
@endforeach
@endif
这是一个想法,在这种情况下,默认情况下,您的评论将0
作为comment_parent
,当一个评论是对另一个评论的回复时,将其comment_parent
设置为其父级的id
。此外,您可以查看本文以了解不同的方法。
我意识到,如果每次从数据库中获取数据时都必须对帖子的所有评论进行排序,那么最终可能会导致性能问题。因此,我的解决方法如下:首先,这是我的评论表:
+-------------------+------------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+------------------+------+-----+---------------------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| content | varchar(2000) | NO | | NULL | |
| author_id | int(10) unsigned | NO | MUL | NULL | |
| post_id | int(10) unsigned | NO | MUL | NULL | |
| parent_comment_id | int(10) unsigned | YES | MUL | NULL | |
| level | tinyint(4) | NO | | 1 | |
| sort_order | int(10) unsigned | NO | | NULL | |
| created_at | timestamp | NO | | 0000-00-00 00:00:00 | |
| updated_at | timestamp | NO | | 0000-00-00 00:00:00 | |
+-------------------+------------------+------+-----+---------------------+----------------+
请注意,有一个名为sort_order的字段,每次有新的评论添加到帖子中时,都会发生以下两件事之一来决定newComment的sort_order值:
如果注释没有父级,则
$newComment->sort_order=注释::max('sort_order')+1;
如果注释有父级,则
$parent = $newComment->parentComment; $newComment->sort_order = $parent->sort_order + 1; // for all the comments that have sort_order larger than the parent of the newly added comment, add their sort_order by 1 $comments_to_be_updated = Comment::where('sort_order', '>', $parent->sort_order)->get(); foreach ($comments_to_be_updated as $comment_to_be_updated) { $comment_to_be_updated->sort_order += 1; $comment_to_be_updated->save(); }
这样,每次添加新的评论时,它的位置/顺序都会被sort_order最终确定并记录下来,当我想获取具有所需顺序的帖子的注释时,我只需要:
$post->comments->orderBy('sort_order')->paginate(10);
现在,我并不是说这是解决方案,但它已经过测试,在我的场景中有效,如果你对数据库性能或其他方面有任何建议/批评,请照做,我愿意接受建议和讨论。