Eloquent: hasNot with parameter
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
# Eloquent: Mastering `hasNot` with Parameters for Complex Queries
Eloquent ORM is one of Laravel's most powerful features, allowing developers to interact with the database using expressive PHP code rather than raw SQL. When dealing with complex relationships—such as finding entities that *lack* a specific association—understanding how to apply conditional constraints like `hasNot` is crucial.
This post dives into a common challenge: fetching all `Posts` that a specific `User` has not yet commented on, utilizing Eloquent's capabilities effectively. We will explore why simple relationship methods might fall short and demonstrate the most efficient, developer-centric way to solve this using query constraints.
## Setting the Scene: Our Models and Relationships
Let's first establish the structure we are working with. We have three core models: `User`, `Post`, and `Comment`. The relationships are defined as follows:
1. A `User` can have many `Comment`s.
2. A `Post` can have many `Comment`s.
The goal is to find all `Post` records associated with a specific `$user` where that user has zero corresponding entries in the `comments` table linked to those posts.
```php
// User Model
class User extends Authenticatable
{
public function comments()
{
return $this->hasMany(Comment::class);
}
}
// Post Model
class Post extends Model
{
public function comments()
{
return $this->hasMany(Comment::class);
}
}
// Comment Model
class Comment extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
}
```
## Why Simple `hasNot` Isn't Enough Here
The built-in `hasNot` method is excellent for checking if a model *has* or *does not have* a relationship. For instance, `$post->hasNot('comments')` checks if the post has zero comments. However, our requirement is more nuanced: we need to check the absence of a specific related record *through an intermediary*. We are not asking, "Does this Post have no Comments?" We are asking, "Does this User have commented on this Post?"
Trying to apply `hasNot` directly across these relationships often leads to complex nested queries or requires defining custom scopes on every model, which can become unwieldy. A more direct and performant approach involves leveraging Eloquent's powerful query scope methods designed for exclusion.
## The Solution: Using `whereDoesntHaveBy`
The most idiomatic and efficient way to solve this problem is by starting the query from the desired model (`Post`) and using the `whereDoesntHaveBy` method. This method allows you to constrain the results based on the absence of a relationship linked via a specific foreign key, making the operation highly optimized by the underlying database engine.
To find all posts that the user has **not** commented on, we need to reverse the logic slightly: we want posts where *no* comment exists linking that `$user` to that `$post`.
Here is the implementation within the `Post` model or wherever you initiate your query:
```php
use App\Models\User;
class Post extends Model
{
public function postsNotCommentedBy(User $user)
{
// Find all Posts where NO Comment exists linking this User and this Post.
return $this->whereDoesntHave('comments', function ($query) use ($user) {
$query->where('user_id', $user->id);
});
}
}
// Usage Example:
$user = User::find(1); // The specific user we are checking for
$posts = Post::whereDoesntHave('comments', function ($query) use ($user) {
$query->where('user_id', $user->id);
})->get();
// $posts now contains all Posts that User 1 has not commented on.
```
### Deeper Dive into the Logic
The magic happens within the closure provided to `whereDoesntHave()`.