在 Laravel Eloquent 中获取和过滤关系
Posted
技术标签:
【中文标题】在 Laravel Eloquent 中获取和过滤关系【英文标题】:Fetching and filtering relations in 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; 【参考方案1】:如果group
hasMany threads
和thread
hasMany comments
,您可以向组添加另一个关系:group
hasMany comments
到threads
。
在群里:
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');
不过有几点需要注意:
-
使用关系对象而不是集合(
$group->comments()
,NOT $group->comments
)
如果你使用 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,然后在第二个查询中批量删除它们。
【讨论】:
区分关系对象 () 和集合,只是大多数关系问题的答案。谢谢!!以上是关于在 Laravel Eloquent 中获取和过滤关系的主要内容,如果未能解决你的问题,请参考以下文章
从父多对多关系获取所有子模型 Laravel Eloquent
从 eloquent builder laravel 7 获取关系数据
Laravel cviebrock/eloquent-sluggable 将 @ 作为前缀或在路由中过滤它
使用 Eloquent 在 Laravel 中使用 where 子句访问嵌套的相关对象