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:
- A
Usercan have manyComments. - A
Postcan have manyComments.
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.
// 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:
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().