【问题标题】:Fetching and filtering relations in Laravel Eloquent在 Laravel Eloquent 中获取和过滤关系
【发布时间】:2015-04-10 18:01:00
【问题描述】:

我在 Eloquent 中有以下模型:组、线程、cmets 和用户。我想从特定用户中找到特定组中的所有 cmets。

这是我目前的做法:

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

这看起来丑得要命,可能慢得要命,我只想摆脱它。在 Eloquent 中获取我的结果集的最快、最优雅的方式是什么?

【问题讨论】:

  • 您想将所有 cmets 合并还是逐个线程?
  • 我真的不在乎。所有的 cmets 组合起来就足够了。
  • 你们的关系怎么样?因为如果您正确设置了关系,您可以执行类似 $group->find(1)->users()>find(1)->cmets;

标签: php sql laravel orm eloquent


【解决方案1】:

如果group hasMany threadsthread hasMany comments,您可以向组添加另一个关系:group hasMany commentsthreads

在群里:

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

现在,您可以通过$group->comments;获取群组中的cmets

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

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

如果需要,您可以将 where 提取到 Comment 的范围内。

【讨论】:

    【解决方案2】:

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

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

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

    不过有几点需要注意:

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

    如果您想从特定组中的特定用户中删除所有 cmets,您必须做一些不同的事情:

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

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

    【讨论】:

    • 区分关系对象 () 和集合,只是大多数关系问题的答案。谢谢!!
    猜你喜欢
    • 2016-10-15
    • 2022-01-03
    • 2014-01-15
    • 2015-04-04
    • 2014-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-14
    相关资源
    最近更新 更多