PHP

Filter Parent Models Based on Related Model Conditions

Efficiently filter parent Eloquent models based on the existence or conditions of their related models using `whereHas` or `has` methods.

<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;

class ReportController extends Controller
{
    public function usersWithPosts()
    {
        // Get users who have at least one post
        $users = User::has('posts')->get();
        // Equivalent SQL: SELECT * FROM users WHERE EXISTS (SELECT * FROM posts WHERE users.id = posts.user_id)
        echo "Users with any posts: " . $users->pluck('name')->implode(', ') . "
";

        // Get users who have posts with 'published' status
        $usersWithPublishedPosts = User::whereHas('posts', function (Builder $query) {
            $query->where('status', 'published');
        })->get();
        // Equivalent SQL: SELECT * FROM users WHERE EXISTS (SELECT * FROM posts WHERE users.id = posts.user_id AND status = 'published')
        echo "Users with published posts: " . $usersWithPublishedPosts->pluck('name')->implode(', ') . "
";

        // Get users who DO NOT have any posts
        $usersWithoutPosts = User::doesntHave('posts')->get();
        echo "Users without any posts: " . $usersWithoutPosts->pluck('name')->implode(', ') . "
";

        // Get users who DO NOT have posts with 'published' status
        $usersWithoutPublishedPosts = User::whereDoesntHave('posts', function (Builder $query) {
            $query->where('status', 'published');
        })->get();
        echo "Users without published posts: " . $usersWithoutPublishedPosts->pluck('name')->implode(', ') . "
";

        return response()->json([
            'users_with_posts' => $users->pluck('name'),
            'users_with_published_posts' => $usersWithPublishedPosts->pluck('name'),
            'users_without_posts' => $usersWithoutPosts->pluck('name'),
            'users_without_published_posts' => $usersWithoutPublishedPosts->pluck('name'),
        ]);
    }
}
How it works: Eloquent's `has()` and `whereHas()` methods are powerful for filtering parent models based on the existence or specific conditions of their related models. `has('relationship')` retrieves parent models that have at least one related record. `whereHas('relationship', function (Builder $query) { ... })` extends this by allowing you to add more specific constraints to the related model's query. Conversely, `doesntHave()` and `whereDoesntHave()` retrieve parent models that do not have any or specific related records, respectively. These methods are crucial for complex relational queries without needing raw SQL joins.

Need help integrating this into your project?

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

Hire DigitalCodeLabs