I have the following models in Eloquent: groups, threads, comments and users. I want to find all comments in a specific group from a specific user.
This is my current approach:
$group->threads->each(function ($thread) use ($user_id)
{
$user_comments = $thread->comments->filter(function ($comment) use ($user_id)
{
return $comment->owner_id == $id;
});
});
This looks ugly as hell, is probably slow as hell, and I just want to get rid of it. What is the fastest and most elegant way in Eloquent to get to my result set?
patricus solution pointed me in the right direction. I cross posted my question to the laracasts Forum and got a lot of help from Jarek Tkaczyk who also frequently visits this site.
hasManyThrough()
for the Group
model is the way to go:
public function comments()
{
return $this->hasManyThrough('ThreadComment', 'Thread');
}
There a couple of caveats, though:
$group->comments()
, NOT $group->comments
)get()
to a delete()
, because you’ll get an ambiguity error for the column updated_at
. You can’t prefix it either, it’s just how Eloquent works.If you want to delete all comments from a specific user in a specific group you’ll have to do it a little bit differently:
$commentsToDelete = $group->comments()
->where('threads_comments.owner_id', $id)
->select('threads_comments.id')
->lists('id');
ThreadComment::whereIn('id', $commentsToDelete)->delete();
You basically fetch all relevant IDs in the first query and then batch delete them in a second one.
If a group
hasMany threads
, and a thread
hasMany comments
, you can add another relationship to group: group
hasMany comments
through threads
.
On the group:
public function comments() {
return $this->hasManyThrough('Comment', 'Thread');
}
Now, you can get the comments in a group by $group->comments;
From here, you can tack on the requirement for the user:
$user_comments = $group->comments()->where('owner_id', $user_id)->get();
If you want, you can extract the where out into a scope on the Comment.