user3718908x100
user3718908x100

Reputation: 8509

Laravel Eloquent whereDoesntHave

I'm having issues using this method, I have read the docs but I am either doing something wrong or not understanding how it works or it's a bug.

I have the following code in my controller:

$books = Book::whereDoesntHave("author", function ($query) {
    $query->whereNotNull("died_at");
})->get();

Now what this is supposed to do is return all books whose authors are still alive and also all books that do not have an author, however it does the exact opposite.

I assumed whereDoesntHave() is supposed to check whether the model doesn't have the specified relation, in this case an author model with the column died_at having a specific value.

Instead it checks the author model where the column died_at doesn't a value.

I'm very confused about this, how is this function supposed to work exactly? Can someone please explain this to me.

Upvotes: 2

Views: 3224

Answers (2)

Salman Malik
Salman Malik

Reputation: 1118

Answering this for anyone who might be looking for an updated answer to a similar question. Using laravel query scopes could be the best approach here:

In your case, you want to retrieve books where the author is either alive or where there is no author. Instead of using whereDoesntHave, you can achieve this using a custom query scope on your Book model. Here's an example of how you can define a query scope for your scenario:

Book.php

// Inside your Book model

public function scopeAliveAuthorsOrNoAuthor($query)
{
    return $query->whereHas('author', function ($subquery) {
        $subquery->whereNull('died_at');
    })->orWhereDoesntHave('author');
}

you can name this function anything as long as it begins with scope for Laravel to identify it as query scope.

Now, in your controller, you can use this scope like this:

$books = Book::aliveAuthorsOrNoAuthor()->get();

As you can see, to apply the scope on our Builder, we can use the scope defined earlier without the word scope in the beginning and it will automagically apply the filter for us. More examples for scope would be scopeWhereAuthorIsAlive($query) and then call it as ``Book::whereAuthorIsAlive()```

Upvotes: 0

rkj
rkj

Reputation: 8287

can you try this, doesntHave("author") check books that doesn't have author and whereHas with closure check live author

$books = Book::doesntHave("author")->orWhereHas("author", function ($query) {
    $query->whereNotNull("died_at");
})->get();

Upvotes: 1

Related Questions