How to Use withExists() to check existance of relationship

Also Read : Refactoring the Legacy Laravel App  How to do image classification using HuggingFace API  Stripe - the best payment gateway. WHY?  Convert data to JSON file  Stripe coupons - delete coupons in Laravel  How to create Database from code  How to get DB size in laravel  How to use Foreach() loop in Blade file  Service Repository architecture pattern - Laravel

A common UI requirement is to display a boolean badge or status indicator based on whether a related record exists. For example, displaying an "Active Subscriber" badge on a user profile, checking whether a post has comments, or checking whether a customer has an unpaid invoice.

Many developers will do a costly eager load of the relationship just to check whether any records exist, or call withCount() just to see if the count is greater than zero. Both are a waste of database resources. Eloquent provides a dedicated method for checking whether a relationship exists, withExists(), which is much more performant.

The Common (Inefficient) Ways

Here are the two ways developers typically check for relationship existence:

// Bad Approach 1: Eager loading the entire relationship
$users = User::with('orders')->get();
foreach ($users as$user) {
    if ($user->orders->isNotEmpty()) {
        // Loads thousands of Order model instances into memory just for a true/false check!
    }
}

// Bad Approach 2: Using withCount()
$users = User::withCount('orders')->get();

foreach ($users as $user) {
    if ($user->orders_count > 0) {
        // Forces the database engine to count EVERY single row
    }
}

Approach 1 hydrates hundreds of model objects into PHP memory. 

Approach 2 makes MySQL count every row, even if an account has 50,000 orders and you only care if they have at least one.

The Efficient Way: withExists()

Laravel's withExists() adds an {relation}_exists boolean attribute directly to each model using a single subquery:

$users = User::withExists('orders')->get();

foreach ($users as $user) {
    if ($user->orders_exists) {
        echo "User has placed orders.";
    }
}

Laravel executes an EXISTS subquery in SQL:

SELECT `users`.*, 
EXISTS(
    SELECT 1 FROM `orders` WHERE `orders`.`user_id` = `users`.`id`
) AS `orders_exists` 
FROM `users`;

The database engine stops scanning the index the moment it finds the first matching row, returning a simple true (1) or false (0).

Adding Conditions and Custom Aliases

You can also pass a closure to constrain the check, or use an alias to give the resulting attribute a clearer name:

$users = User::withExists([
    'subscriptions' => function ($query) {$query->where('status', 'active');
    },
    'orders as has_pending_orders' => function ($query) {$query->where('status', 'pending');
    },
])->get();

foreach ($users as$user) {
    if ($user->subscriptions_exists) {
        // Active subscriber
    }

    if ($user->has_pending_orders) {
        // Pending order exists
    }
}

Why withExists() Beats withCount()

Method Database Work PHP Memory Best Used For
with('relation') Loads all columns for every row High (hydrates full models) When you need to iterate child records.
withCount('relation') Counts every matching row in index Low (appends integer) When you need to show numbers like "42 Comments".
withExists('relation') Stops at first match (EXISTS) Low (appends boolean) When you only need a true/false check.

Summary

Do not load models or run aggregated count queries if you only need to know if a record exists. Instead, you can use the much more efficient withExists() method that will allow the database to return a lightweight boolean flag, saving you precious disk and memory resources.

Thank you for reading this article 😊

For any query, do not hesitate to comment 💬


Previous Post Next Post

Contact Form