Understanding withWhereHas() in Laravel

Understanding withWhereHas() in Laravel

Here we will see working with Eloquent relationships; it’s common to filter parent records based on their related data. Laravel provides the whereHas() method for this, but there’s a small problem that many developers encounter.

Suppose you want to retrieve users who have published posts and also display only those published posts. Using whereHas() alone filters the users correctly, but when you access the relationship, Laravel still loads all of the user’s posts unless you apply the same condition again using with().

Laravel solves this problem with the withWhereHas() method.

Prerequisites

  • Composer (Latest Version) 
  • Laravel 12

Steps to use withWhereHas() in Laravel 12

  1. Create a new Laravel project
  2. models and migration
  3. Define the relationship
  4. Create routes
  5. Create a controller
  6. Test the output

Step  1: Create a New Laravel Project

composer create-project laravel/laravel withwherehas-demo

Step  2: Create Models and Migration

php artisan make:model Post -m

Update the posts migration.

Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->constrained()->cascadeOnDelete();
    $table->string('title');
    $table->enum('status', ['draft', 'published']);
    $table->timestamps();
});

Run the migration.

php artisan migrate

Step  3: Define the Relationship

Now, open the User model, and edit as below,

public function posts()
{
    return $this->hasMany(Post::class);
}

Now open the Post model.

public function user()
{
    return $this->belongsTo(User::class);
}

After that, add the dummy data.

Step  4: Create Routes

use App\Http\Controllers\UserController;
Route::get('/users', [UserController::class, 'index']);

Step  5: Create a Controller

php artisan make:controller UserController

Now open the controller and edit it as follows,

<?php
namespace App\Http\Controllers;
use App\Models\User;
class UserController extends Controller
{
    public function index()
    {
        $users = User::withWhereHas('posts', function ($query) {
            $query->where('status', 'published');
        })->get();
        return response()->json($users);
    }
}

Step  6: Test the Output

To see the output, you need to open the browser:

http://127.0.0.1:8000/users

You will get the result as below.

[
    {
        "id": 1,
        "name": "test user",
        "email": "user@gmail.com",
        "posts": [
            {
                "id": 1,
                "title": "Laravel Post",
                "status": "published",
                "user_id": 1
            }
        ]
    }
]

Conclusion:

The withWhereHas() method is a convenient way to combine the functionality of whereHas() and with() into a single query.

FAQ

1. What is withWhereHas() in Laravel?

withWhereHas() is an Eloquent method that combines whereHas() and with() into a single query. It filters parent models based on relationship conditions while eager loading only the matching related records.

2. Is withWhereHas() better than using whereHas() and with() separately?

Yes. It provides the same functionality with less code, making your queries cleaner, easier to maintain, and less prone to errors.

3. Is withWhereHas() available in Laravel 12?

Yes. withWhereHas() is fully supported in Laravel 12 and is recommended whenever you need to filter and eager load the same relationship using identical conditions.

Previous Article

Best Adobe Experience Manager Alternatives for Brand Portfolios

Write a Comment

Leave a Comment

Your email address will not be published. Required fields are marked *

Get Connect With Us

Subscribe to our email newsletter to get the latest posts delivered right to your email.
Pure inspiration, zero spam ✨