Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[5.7] Fix nested whereDoesntHave() #26228

Merged
merged 1 commit into from
Oct 29, 2018
Merged

[5.7] Fix nested whereDoesntHave() #26228

merged 1 commit into from
Oct 29, 2018

Conversation

staudenmeir
Copy link
Contributor

doesntHave() and whereDoesntHave() don't work properly with nested relationships:

User::whereDoesntHave('posts.comments', function ($query) {
    $query->where('spam', true);
})->get());

Eloquent applies the not exists clause to the innermost relationship instead of the outermost:

select * from "users" where exists (
  select * from "posts" where "users"."id" = "posts"."user_id" and not exists (
    select * from "comments" where "posts"."id" = "comments"."post_id" and "spam" = 1
  )
)

This causes incorrect results (fiddle):

  • It returns users that have posts with spam comments and posts without spam comments (user 1).
  • It doesn't return users that don't have any posts at all (user 2).

You get the correct query when you nest the closures yourself:

User::whereDoesntHave('posts', function ($query) {
    $query->whereHas('comments', function ($query) {
        $query->where('spam', true);
    });
})->get();
select * from "users" where not exists (
  select * from "posts" where "users"."id" = "posts"."user_id" and exists (
    select * from "comments" where "posts"."id" = "comments"."post_id" and "spam" = 1
  )
)

Fixes #26222.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants