framework
framework copied to clipboard
[9.x] Constraint withWhereHas on nested relationships
Related to this issue: https://github.com/laravel/framework/issues/44159
Calling withWherehas with a nested relationship and without a callback, the method returns all related models from the parent relationship even if it has no children.
SomeModel::withWhereHas('parent.child');
In that case, it will return only SomeModel where the parent has child but it would eagerly load every parent related to SomeModel not only those that have a child.
Another less abstract example:
$user = User::factory()->create();
Comment::factory()
->for($user)
->for(Thread::factory()->trashed()) // soft deleted thread
->create();
Comment::factory()
->for($user)
->for(Thread::factory())
->create();
User::query()
->withWhereHas('comments.thread')
->get();
Here it would be expected for the query to return the User model with exactly one comment (the one that has the non-deleted thread). But, instead, we get the User with the two comments, one with the thread as null.
You can circumvent this by passing a callback that calls withWhereHas with the nested relationship:
User::query()
->withWhereHas('comments', function ($query) => {
$query->withWhereHas('thread');
})
->get();
With this pull request that is the generated query when calling withWhereHas with a nested relationship and no callback.
If you think the current behavior makes more sense feel free to close this pull request.