WhereHas() is a Laravel eloquent method, which helps to define additional query constraints on your queries, such as filtering your books with some author name. For example, return all the books if it matches an author named Charles Dickens. But whereHas() often confused with some other terms in Laravel, has() and with(), which is very confusing for new developers.
Before we start with the whereHas, we will go through the with() and has() methods.
First of all, we examine with() method,:
with()
The related models are lazy-loaded when accessing eloquent relationships as properties. It means the actual relationship data is not loaded until you call the property. So Laravel with() method helps to eager load values. What this means is, along with the main model, Laravel preloads the relationships, which results in fewer database queries.
In the event of multiple models, and you need to load them at once, this method is really efficient, and it reduces the database interaction as it calls the database only once. With eager loading, you run only one additional database query instead of one for every model in the collection.
Example
$posts = Post::with('comments')->get(); foreach($posts as $post){ $post->comments; }
Comments are already loaded and no additional DB query is run
has()
Let’s say we have posts and comments, with a 1-n relationship, and one Post can have many comments.
So our Post model will look like below
public function comments(){ return $this->hasMany(\App\Models\Comment::class, 'post_id'); }
Think, what if we want to show only posts with at least one comment. Here comes our has() method to rescue.
$posts = Post::has('comments')->get();
whereHas()
So we are back to our original Topic, ie whereHas() method. So it works almost the same as has() method, but it allows you have additional conditions on the related models.
$posts = Post::whereHas('comments', function($q){ $q->where('status', '=', 'active'); })->get(); // only posts that have comments that is active will be returned
Example usage of whereHas() with with()
$posts = Post::whereHas('comments', function ($query) { $query->where('content', 'like', 'foo%'); })->with(['comments' => function ($query) { $query->where('content', 'like', 'foo%'); }])->get();
Also, this can be rewritten like the below, which is much cleaner and avoiding code duplication.
$callback = function($query) { $query->where('something', '=', 'something'); } $posts = Post::whereHas('comments', $callback)->with(['comments' => $callback])->get();
- Just want to thank us? Buy us a Coffee
- May be another day? Shop on Amazon using our links.
Your prices won't change but we get a small commission.
Leave a Reply