Clean Relationship Filtering in Laravel Using withWhereHas()
In Laravel, when working with relationships, you often need to:
- Filter parent models
- Load only specific related records
Laravel provides a clean solution: withWhereHas().
🔹 Basic Usage
User::withWhereHas('orders', function ($q) {
$q->where('status', 'paid');
})->get();
👉 This will:
- Return users who have paid orders
- Load only those paid orders
🔹 Using with Multiple Conditions
User::withWhereHas('orders', function ($q) {
$q->where('status', 'paid')
->where('amount', '>', 1000);
})->get();
👉 Filters both user and related orders together.
🔹 Real Project Example
Imagine showing users with premium purchases:
$users = User::withWhereHas('orders', function ($q) {
$q->where('plan', 'premium');
});
Now:
- Only users with premium orders are returned
- Only premium orders are loaded
🔹 Nested Relationship Usage
User::withWhereHas('orders.items', function ($q) {
$q->where('type', 'digital');
})->get();
👉 Works even for deeper relationships.
🎯 Why Use withWhereHas()
- Keeps conditions in one place
- Avoids duplication
- Improves readability
- Reduces mistakes in queries
🧠When to Use It
Use it when:
- Filtering relationships
- Eager loading with conditions
- Building APIs with relational data