Fetching and filtering relations in Laravel Eloquent
Solution 1
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:
- Use the relation object instead of a collection (
$group->comments()
, NOT$group->comments
) - If you use Laravel’s soft deletes you can’t just change the
get()
to adelete()
, because you’ll get an ambiguity error for the columnupdated_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.
Solution 2
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.
Rafael Bugajewski
One half of Cocobit. My wife and I make great software for your iPhone, iPad & Mac 🤓
Updated on February 12, 2020Comments
-
Rafael Bugajewski about 4 years
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?
-
zardilior over 5 yearsMaking the difference between relation object () and collection, is just the answer to most realtionship issues. Thanks!!