PHP

Filter Parent Models Based on Related Model Criteria with `whereHas`

Efficiently retrieve parent models only if their related models meet specific criteria, avoiding unnecessary data loading and improving query performance.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    use HasFactory;

    public function products()
    {
        return $this->hasMany(Product::class);
    }
}

class Product extends Model
{
    use HasFactory;

    public function category()
    {
        return $this->belongsTo(Category::class);
    }
}

// Usage:
// Retrieve categories that have at least one product with 'available' status and price > 100
// $categoriesWithAvailableProducts = Category::whereHas('products', function ($query) {
//     $query->where('status', 'available')
//           ->where('price', '>', 100);
// })->get();

// Find users who have at least one published post
// $usersWithPublishedPosts = User::whereHas('posts', function ($query) {
//     $query->where('status', 'published');
// })->get();

// You can also use 'orWhereHas' for OR conditions
// $categoriesWithCheapOrExpensiveProducts = Category::whereHas('products', function ($query) {
//     $query->where('price', '<', 50);
// })->orWhereHas('products', function ($query) {
//     $query->where('price', '>', 500);
// })->get();
How it works: The `whereHas` method allows you to filter results based on the existence of related models that satisfy specific conditions. Instead of loading all related models and then filtering, `whereHas` generates an efficient SQL `WHERE EXISTS` subquery, which significantly improves performance by only retrieving the parent models that meet the relationship criteria, making it ideal for filtering lists based on related data.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs