PHP
Filtering Eloquent Models by Related Model Existence
Discover how to filter parent models based on the existence or specific conditions of their related child models using Eloquent's `whereHas` and `has` methods.
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Category extends Model
{
public function products(): HasMany
{
return $this->hasMany(Product::class);
}
}
class Product extends Model
{
// ...
}
// Usage:
// Get categories that have at least one product
// $categoriesWithProducts = Category::has('products')->get();
// Get categories that have at least 5 products
// $categoriesWithManyProducts = Category::has('products', '>=', 5)->get();
// Get categories that have at least one product with 'active' status
// $categoriesWithActiveProducts = Category::whereHas('products', function ($query) {
// $query->where('status', 'active');
// })->get();
// Get categories that *do not* have any products (whereDoesntHave)
// $categoriesWithoutProducts = Category::doesntHave('products')->get();
// Get categories that *do not* have any products with 'active' status (whereDoesntHave)
// $categoriesWithoutActiveProducts = Category::whereDoesntHave('products', function ($query) {
// $query->where('status', 'active');
// })->get();
How it works: The `has` and `whereHas` methods in Eloquent are used to filter parent models based on the existence or specific conditions of their related models. `has()` checks if a relationship has at least one matching record (or a specified count). `whereHas()` allows you to add custom constraints to the related model's query, filtering the parent models based on the specific attributes of their children. `doesntHave()` and `whereDoesntHave()` provide the inverse functionality.