Laravel深度第一棵树遍历

时间:2014-09-30 12:12:12

标签: mysql laravel

所以我使用的php框架是Laravel。我有一个评论表,评论允许有孩子评论。我按更新时间订购了评论:

$post->comments()->orderBy('updated_at')->paginate(10);

现在我想对注释进行分组,以便将具有相同父注释的所有子注释放在一起,即父注释,然后是所有子注释,然后是下一个父注释,然后是所有子注释评论一个一个,等等。如下:

  • 注释1
  • 评论1的子评论
  • 评论1的子评论B
  • 注释2
  • 评论2的子评论C.
  • 评论2的子评论
  • subcommentD的子评论
  • ...

现在这个订单不能通过一个简单的订单来完成,我的问题是:我可以用Laravel查询构建器/ eloquent完成这个,还是我必须手动订购?顺便说一句,我已经设置了Comment模型,以便可以通过以下方式获取其父/子:

$comment->parentComment;
$comment->childComments;

2 个答案:

答案 0 :(得分:0)

您可以使用模型关系(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'发表了两条儿童评论s是user_id-2user_id-3

此处,comment_parent列保留parentchild条评论之间的关系。值comment_parent的{​​{1}}是父评论,而不是0,例如,此处有两条评论0 comment_parent,这意味着这两条评论是1id/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。此外,您可以检查this article是否有其他方法。

答案 1 :(得分:0)

我意识到如果每次从数据库中获取数据时都要订购帖子的所有评论,最终可能会导致严重的性能问题。所以我的解决方法如下: 首先,这是我的评论表:

+-------------------+------------------+------+-----+---------------------+----------------+
| 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的值:

  1. 如果评论没有父母,那么

    $ newComment-&gt; sort_order = Comment :: max('sort_order')+ 1;

  2. 如果评论有父级,那么

    $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完成并记录,当我想要获取具有所需顺序的帖子的评论时,我只需要:

    $后&GT;评论 - &GT; ORDERBY( 'SORT_ORDER') - &GT;分页(10);

  3. 现在,我不是说这是解决方案,但它已在我的方案中经过测试和运行,如果您对数据库性能或任何事情有任何建议/批评,请做,我愿意接受建议和讨论