PHP
Filtering Models Based on Related Records (has/whereHas)
Filter parent models in Laravel Eloquent based on the existence or specific attributes of their related child records using `has` and `whereHas` methods.
use App\Models\Post;
use App\Models\User;
// Get all posts that have at least one comment.
$postsWithComments = Post::has('comments')->get();
// Get all posts that have at least 5 comments.
$postsWithManyComments = Post::has('comments', '>=', 5)->get();
// Get all posts that have comments by a specific user (e.g., user ID 1).
$postsWithUserComments = Post::whereHas('comments', function ($query) {
$query->where('user_id', 1);
})->get();
// Get all posts that have comments with 'bad_word' in their body.
$postsWithProfaneComments = Post::whereHas('comments', function ($query) {
$query->where('body', 'like', '%bad_word%');
})->get();
// Get all users who have not placed any orders (using 'doesntHave').
$usersWithoutOrders = User::doesntHave('orders')->get();
// Get all users who have not placed any 'completed' orders (using 'whereDoesntHave').
$usersWithoutCompletedOrders = User::whereDoesntHave('orders', function ($query) {
$query->where('status', 'completed');
})->get();
How it works: The `has` and `whereHas` methods are powerful for querying parent models based on their relationships. `has` checks for the mere existence of at least one related record (e.g., 'posts that have comments'). `whereHas` takes a closure, allowing you to add specific constraints to the relationship query itself, filtering parent models based on conditions within their related child records (e.g., 'posts that have comments by a specific user'). Similarly, `doesntHave` and `whereDoesntHave` can be used to retrieve models that do NOT have certain relationships or related records matching specific criteria.