在 Laravel Eloquent 中获取和过滤关系


Fetching and filtering relations in Laravel Eloquent

我在Eloquent中有以下模型:组,线程,评论和用户。我想查找特定用户在特定组中的所有评论。

这是我目前的方法:

$group->threads->each(function ($thread) use ($user_id)
{
  $user_comments = $thread->comments->filter(function ($comment) use ($user_id)
  {
    return $comment->owner_id == $id;
  });
});

这看起来丑陋如地狱,可能慢如地狱,我只想摆脱它。在 Eloquent 中,访问我的结果集的最快、最优雅的方式是什么?

如果一个group有很多threads,而一个thread有很多comments,你可以向组添加另一个关系:group有很多commentsthreads

在组中:

public function comments() {
    return $this->hasManyThrough('Comment', 'Thread');
}

现在,您可以按$group->comments;在组中获取评论

从这里,您可以满足用户的要求:

$user_comments = $group->comments()->where('owner_id', $user_id)->get();

如果需要,您可以将 where 提取到注释的范围中。

patricus解决方案为我指明了正确的方向。我把我的问题交叉发布到laracasts论坛,并从Jarek Tkaczyk那里得到了很多帮助,他也经常访问这个网站。

Group模型的hasManyThrough()是要走的路:

public function comments()
{
  return $this->hasManyThrough('ThreadComment', 'Thread');
}

不过,有几个警告:

  1. 使用关系对象而不是集合($group->comments()而不是$group->comments(
  2. 如果你使用Laravel的软删除,你不能只是将get()更改为delete(),因为你会收到列updated_at的歧义错误。你也不能给它加上前缀,这就是 Eloquent 的工作方式。

如果你想删除特定组中特定用户的所有评论,你必须采取一些不同的做法:

$commentsToDelete = $group->comments()
        ->where('threads_comments.owner_id', $id)
        ->select('threads_comments.id')
        ->lists('id');
ThreadComment::whereIn('id', $commentsToDelete)->delete();

您基本上在第一个查询中获取所有相关 ID,然后在第二个查询中批量删除它们。