Framework: [Request] Eloquent: hasNot() method for many-to-many relationships

Created on 31 Jan 2014  路  32Comments  路  Source: laravel/framework

The has() method is very handy in a many-to-many relationship when used to find the model instances where the relationship exists.
In some cases, though (for example: "users who have _not_ an assigned role") a hasNot() method returning the results where the relationship _doesn't_ exist would be useful.

$users = User::hasNot("role")->get();

Most helpful comment

doesntHave already exists people?

All 32 comments

Good idea. It can just be an alias for something that's already possible: User::has('role', '<', 1)

As noted above, its currently possbile by using the < 1 operator.

A hasNot method would be much better.

:+1:

hasNot would definitely look better!

+1 for this

I agree, having this would increase code readability.

+1

@taylorotwell (as far as I can understand) It doesn't have the same functionality to full extend. I needed something like this;

$users = User::hasNot("role", function($q) {
  $q->where('name', 'moderator');
})->get();

I'd like to get users with no moderator role attached (as an example). I cannot find a simple and proper way for it.

:+1:

@furkanmustafa In the laravel API docs http://laravel.com/api , the whereHas function is documented to also support the operater and count argument.

Builder|Builder whereHas(string $relation, Closure $callback, string $operator = '>=', int $count = 1)

$users = User::whereHas("role", function($q) {
  $q->where('name', 'moderator');
}, '<', 1)->get();

@ricksuggs ah! ok. even if it doesn't read as I hoped, that's still a complete solution. thanks.

As a side note, if it ever does get implemented solely for readability, wouldn't this be more readable (doesNotHave vs hasNot):

$users = User::doesNotHave("role")->get();

@ricksuggs If we have doesNotHave we need to have doesHaveinstead of has. So hasNot is better IMO.

I create a PR.

+1 For hasNot

@gowthamSelvaraj Already added https://github.com/laravel/framework/pull/6686.

How about an orDoesntHave function?

+1 for hasNot()

+1 for hasNot() too

Working on a solution to filter users by role right now.
I'll work with the solution given above, but I've "instinctively" tried "hasNot" before.

+1 for hasNot()

Exactly, but not with the OR statement.

+1 for hasNot()

i cant see this in laravel 5.3 Builder Class? has this been removed?

@Alexwijn

Exactly, but not with the OR statement.

Thats true, but you can always reverse the order:

$query->whereHas('something')->orWhereDoesntHave('something_else')
//fails

=> will not work since method orWhereDoesntHave does not exist
But you can refactor this into:

$query->whereDoesntHave('something_else')->orWhereHas('something')
//works

+1 hasNot()

+1 hasNot()

+1 hasNot()

+1 hasNot()

doesntHave already exists people?

But like I said a long time go, it does not exist with the OR statement.

According to the source we can pass OR as a second parameter:

$query->doesntHave('relationName', 'OR');
Was this page helpful?
0 / 5 - 0 ratings