Laravel - Eloquent "Has", "With", "WhereHas" - What do they mean?

with() eager loads relationships to prevent N+1 queries. has() filters models by relationship existence. whereHas() adds conditions to relationship filters. Use with() for loading data, has()/whereHas() for query scoping.

Laravel - Eloquent "Has", "With", "WhereHas" - What do they mean? Image

When working with Laravel's Eloquent ORM, you'll frequently encounter three powerful methods: has(), with(), and whereHas(). These methods help you work with model relationships efficiently, but they serve different purposes. Let's break down each one with examples to understand when and how to use them.

1. Eager Loading with with()

The with() method is used for eager loading relationships. This means Laravel will perform a single query to get all related models upfront, rather than making additional queries when you access the relationship later (the "N+1 problem").

// Get all posts with their comments (eager loaded)
$posts = Post::with('comments')->get();
foreach ($posts as $post) {
    // No additional query is executed here
    echo count($post->comments);
}

When to use with():

  • When you know you'll need the related data
  • To optimize performance by reducing queries
  • When displaying lists of models with their relationships

2. Filtering with has()

The has() method filters the parent models based on the existence of a relationship. It doesn't load the related models - it just checks if they exist.

// Get only posts that have at least one comment
$postsWithComments = Post::has('comments')->get();
// Get posts that have more than 5 comments
$popularPosts = Post::has('comments', '>', 5)->get();

When to use has():

  • When you want to filter models based on whether they have related records
  • When you don't need the actual related data, just the existence check

3. Conditional Filtering with whereHas()

The whereHas() method is like has() but lets you add additional conditions to the relationship query. It's more powerful and flexible.

// Get posts that have at least one approved comment
$posts = Post::whereHas('comments', function ($query) {
    $query->where('approved', true);
})->get();
// Get users who have written posts with a specific tag
$users = User::whereHas('posts.tags', function ($query) {
    $query->where('name', 'laravel');
})->get();

When to use whereHas():

  • When you need to filter based on conditions in related models
  • When you need more complex relationship constraints than has() provides

Key Differences Summary

MethodPurposeLoads Relationship Data?
with()Eager loadingYes
has()Filter by relationship existenceNo
whereHas()Filter by relationship conditionsNo

Combining Methods

You can combine these methods for powerful queries:

// Get posts with approved comments, and eager load those comments
$posts = Post::whereHas('comments', function ($query) {
    $query->where('approved', true);
})
->with(['comments' => function ($query) {
    $query->where('approved', true);
}])
->get();

Performance Considerations

  • Use with() to avoid the N+1 query problem
  • Use has() and whereHas() to reduce the result set before loading data
  • Remember that whereHas() can be slower than has() for simple existence checks

Understanding these three methods will help you write more efficient Eloquent queries and build better-performing Laravel applications.

Happy Coding! 😊

Do you Like?