PHP
Filter Eloquent Models by Related Data Existence
Efficiently filter parent Eloquent models based on the existence of their related models or specific conditions within those relationships using `has()`, `whereHas()`, and `doesntHave()` methods in Laravel.
<?php
// Find all users who have at least one post
$usersWithPosts = App\Models\User::has('posts')->get();
echo "Users with at least one post:
";
foreach ($usersWithPosts as $user) {
echo "- " . $user->name . "
";
}
// Find all users who have at least 5 posts
$usersWithManyPosts = App\Models\User::has('posts', '>=', 5)->get();
echo "
Users with 5 or more posts:
";
foreach ($usersWithManyPosts as $user) {
echo "- " . $user->name . "
";
}
// Find all users who have at least one published post
$usersWithPublishedPosts = App\Models\User::whereHas('posts', function ($query) {
$query->where('status', 'published');
})->get();
echo "
Users with at least one published post:
";
foreach ($usersWithPublishedPosts as $user) {
echo "- " . $user->name . "
";
}
// Find all users who do NOT have any posts
$usersWithoutPosts = App\Models\User::doesntHave('posts')->get();
echo "
Users without any posts:
";
foreach ($usersWithoutPosts as $user) {
echo "- " . $user->name . "
";
}
How it works: Eloquent provides powerful methods to filter parent models based on their relationships. The `has()` method retrieves models that have at least one related record. You can specify a count constraint (e.g., `has('posts', '>=', 5)`) to filter by the number of related records. For more granular control, `whereHas()` allows you to add specific conditions to the relationship query itself, fetching only users with posts that meet certain criteria (e.g., published posts). Conversely, `doesntHave()` retrieves models that have no related records for a given relationship.