Posted by Kosal
In Laravel 12.8, a powerful new feature landed: withRelationshipAutoloading()
. If you've ever battled the N+1 query problem, or tired of manually chaining .load()
and .with()
all over your models, this new method is about to make your life a lot easier.
This article will break down how withRelationshipAutoloading()
works, why it’s useful, and where it fits in your Laravel toolbox.
withRelationshipAutoloading()
?Think of withRelationshipAutoloading()
as intelligent lazy eager loading.
Normally in Laravel, if you don't specify relationships up front, accessing related data will trigger multiple extra queries—one for each record (the dreaded N+1 problem). Eager loading (with()
) fixes that, but it requires you to know exactly which relationships you’ll need in advance.
withRelationshipAutoloading()
sits in between:
It allows you to load relationships only when accessed, but does so efficiently by batching queries on-the-fly.
Here’s a basic example.
$orders = Order::all()->withRelationshipAutoloading();
foreach ($orders as $order) {
echo $order->customer->profile->email;
}
You didn’t load customer
or profile
in advance. But Laravel is smart enough to detect that you’re accessing those relationships, and runs optimized bulk queries behind the scenes.
Instead of making a query per order, it executes:
$orders->loadMissing('customer');
$orders->loadMissing('customer.profile');
All automatically.
Let’s say you’re working on a project dashboard:
$projects = Project::all()->withRelationshipAutoloading();
foreach ($projects as $project) {
echo $project->client->company->name;
echo $project->posts->first()?->author->name;
}
Without withRelationshipAutoloading()
, you’d need something like this:
$projects = Project::with([
'client.company',
'posts.author'
])->get();
Not only is that longer, but it also loads relationships even if you don’t end up using them. Wasteful!
$tasks = Task::all()->withRelationshipAutoloading();
foreach ($tasks as $task) {
if ($task->is_completed) {
echo $task->completedBy->name;
}
}
You don’t always need completedBy
, so eager loading it everywhere would be inefficient. This approach loads only what’s used, when it’s used — without per-record queries.
Don’t want to call withRelationshipAutoloading()
every time? You can turn it on globally:
use Illuminate\Database\Eloquent\Model;
Model::automaticallyEagerLoadRelationships();
Once enabled, all your model collections will batch-load relationships as needed throughout your app.
✅ Use it when:
❌ Avoid it when:
Always profile your queries!
Install Debugbar:
composer require barryvdh/laravel-debugbar --dev
This lets you see exactly which queries Laravel is running, so you can confirm that withRelationshipAutoloading()
is doing its job efficiently.
$users = User::where('status', 'active')
->withRelationshipAutoloading()
->paginate(20);
foreach ($users as $user) {
echo $user->profile->location;
echo $user->orders->count();
}
No need to eager load profile
or orders
explicitly. Laravel will batch load them only when accessed — and only the ones on this page.
Laravel’s withRelationshipAutoloading()
gives you the best of both worlds:
If your app has grown past a few simple models and you’re constantly juggling which relationships to eager load, this is a must-have feature.
Just don’t forget: power tools are best used carefully. Monitor your queries, test thoroughly, and don’t go overboard.
Feature | Description |
---|---|
with() |
Manually eager load specific relationships upfront |
load() / loadMissing() |
Load relationships later, usually after fetching data |
withRelationshipAutoloading() |
Automatically detect and batch-load relationships as they’re accessed |
automaticallyEagerLoadRelationships() |
Globally enable relationship autoloading for all models |
Want to level up your Laravel skills even more? Follow along for deeper dives into Laravel 12+ features and performance best practices. 🚀