How to use withTrashed when I'm querying using eager loading?
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
# How to Use `withTrashed()` When Querying Using Eager Loading in Laravel
As developers working with relational databases and Eloquent in Laravel, we frequently encounter scenarios involving soft deletes. When you employ soft deletes on a modelâsuch as marking a user as deleted instead of physically removing the rowâeager loading relationships can become surprisingly tricky. A common pitfall arises when trying to load related data for records that might themselves be in a deleted state.
This post details the specific problem you are facing: how to ensure that an eager loaded relationship, which relies on standard Eloquent constraints, still includes soft-deleted parent models, and how to achieve this cleanly.
## The Problem with Standard Eager Loading
You have a setup where your `Appointment` model has a relationship to the `User` model, and the `User` model uses the `SoftDeletes` trait.
When you execute a standard eager load:
```php
$appointments = Appointment::with('user')->get();
```
Eloquent attempts to fetch the related `user` for each appointment. If the associated user has been soft-deleted, by default, Eloquentâs query logic filters out any records where the `deleted_at` column is populated (or implicitly relies on the standard model constraints). Consequently, when you try to access `$appointment->user->full_name`, if the user record is gone from the active set, you encounter errors or null values because the eager load failed to retrieve the soft-deleted relationship.
Your attempt to add `withTrashed()` directly to the main query (`Appointment::withTrashed('user')`) only affects the primary query constraints and doesn't automatically adjust how the *eager loaded* relationship is resolved.
## The Solution: Applying `withTrashed()` to the Relationship
To instruct Eloquent to include soft-deleted models within an eager load, you need to apply the `withTrashed()` scope directly to the relationship definition during the eager loading phase. This tells Eloquent to bypass the default `where deleted_at is null` constraint specifically for that loaded relationship.
Here is how you correctly modify your query to ensure all related users are fetched, regardless of their deletion status:
```php
$appointments = Appointment::with(['user' => function ($query) {
$query->withTrashed();
}])->get();
```
### Detailed Explanation and Code Example
By using a closure when defining the eager load (`with()`), we gain fine-grained control over the constraints applied to the related models.
```php
// Assuming Appointment has a 'user' relationship defined
$appointments = Appointment::with(['user' => function ($query) {
// This ensures that the eager loading query for the 'user' relationship
// includes soft-deleted users.
$query->withTrashed();
}])->get();
$return = array();
foreach ($appointments as $key => $appointment) {
$return[] = array(
$appointment->customer_name,
$appointment->date->format('d/m/Y'),
$appointment->time,
$appointment->status,
// Now this will succeed because the eager load included the deleted user
$appointment->user->full_name,
);
}
// $return now holds all data correctly, even for soft-deleted users.
```
### Why This Works
This approach is effective because it modifies the underlying SQL query generated by Eloquent specifically for loading the related `users`. Instead of simply joining based on active records, you are explicitly telling the database layer to include rows matching the `deleted_at` criteria when fetching the user data associated with each appointment.
This technique demonstrates a powerful level of control over your data retrieval, which is fundamental to building robust applications in Laravel. For more advanced Eloquent features and understanding how these scopes interact within the framework, I highly recommend exploring the official documentation at [https://laravelcompany.com](https://laravelcompany.com).
## Conclusion
Handling soft-deleted relationships during eager loading requires moving beyond simple scope application on the main query. By leveraging a closure within the `with()` method to apply `withTrashed()` directly to the relationship query, you can successfully load related data for both active and soft-deleted records simultaneously. This results in clean, predictable data retrieval, avoiding errors and ensuring your application displays all necessary information.