The Dev Log › Programming
10 Laravel Eloquent Tricks I Use on Every Project
By Jezer Niel Blanca, Full Stack Developer ·
·
3 min read
Small Eloquent habits that keep my Laravel codebases fast, readable, and free of N+1 surprises.
Eloquent is one of the main reasons I keep choosing Laravel. It's expressive enough to read like English, but it's also easy to misuse in ways that quietly slow an app down. These are the ten habits I bring to every project.
1. Turn On Strict Mode in Development
One line in AppServiceProvider::boot() catches lazy loading, silently discarded attributes, and missing attributes before they reach production:
use Illuminate\Database\Eloquent\Model;
Model::shouldBeStrict(! app()->isProduction());
If you only adopt one trick from this list, make it this one.
2. Eager Load with Constraints
Eager loading fixes N+1 queries, and constraints keep the payload small:
$projects = Project::query()
->with(['tasks' => fn ($query) => $query->where('is_done', false)->latest()])
->get();
Laravel 12 also lets you limit eager-loaded records per parent natively, so ->latest()->limit(3) inside the closure works as you'd expect.
3. Count Without Loading
Need a count of related records? Don't load them:
$users = User::query()->withCount('posts')->get();
$users->first()->posts_count;
withSum, withAvg, withMax, and withExists follow the same pattern.
4. Use the Scope Attribute
Local scopes keep repeated query logic in one place. In modern Laravel you can mark a protected method with the Scope attribute:
use Illuminate\Database\Eloquent\Attributes\Scope;
use Illuminate\Database\Eloquent\Builder;
#[Scope]
protected function active(Builder $query): void
{
$query->where('status', 'active');
}
Then call it fluently: Customer::query()->active()->get().
5. Cast to Enums and Value Objects
Casting turns raw database columns into rich types automatically:
protected function casts(): array
{
return [
'status' => OrderStatus::class,
'options' => 'array',
'shipped_at' => 'datetime',
];
}
Now $order->status is an enum instance with methods, not a string you have to compare everywhere.
6. Accessors That Read Clearly
Accessors and mutators use a single Attribute method:
use Illuminate\Database\Eloquent\Casts\Attribute;
protected function fullName(): Attribute
{
return Attribute::make(
get: fn () => "{$this->first_name} {$this->last_name}",
);
}
7. Chunk or Lazy Load Big Datasets
Loading a hundred thousand rows with get() is a memory problem waiting to happen. Use lazy() or chunkById() instead:
User::query()
->where('is_subscribed', true)
->lazyById(500)
->each(fn (User $user) => $user->notify(new WeeklyDigest));
Use chunkById or lazyById when you're updating the rows you're iterating over. Plain offset chunking can skip records.
8. updateOrCreate and upsert
For idempotent writes, updateOrCreate is perfect for single records. For bulk writes, upsert does it in one query:
Price::query()->upsert(
[
['sku' => 'A-100', 'amount' => 1200],
['sku' => 'B-200', 'amount' => 3400],
],
uniqueBy: ['sku'],
update: ['amount'],
);
9. Subquery Selects Instead of Loops
Want each user's latest login date without loading every login? Add it as a subquery column:
$users = User::query()
->addSelect(['last_login_at' => Login::query()
->select('created_at')
->whereColumn('user_id', 'users.id')
->latest()
->limit(1),
])
->get();
One query, no N+1, and the result is sortable.
10. Prevent Mass Assignment Surprises
I always define $fillable explicitly and pass validated data from Form Requests:
$project = $request->user()->projects()->create($request->validated());
Creating through the relationship sets the foreign key for you, and validated() guarantees only checked fields get through.
Bonus: Know What SQL You're Running
When a page feels slow, dump the query:
Project::query()->with('tasks')->where('is_archived', false)->dumpRawSql();
Pair that with Laravel's query log or a debugging tool and most performance mysteries solve themselves.
Wrapping Up
None of these tricks are exotic. They're small defaults that add up to an app that stays fast as data grows and stays readable as the team grows.
Building something on Laravel and want a second pair of eyes on the data layer? Let's talk.
Tags: Laravel, Eloquent, PHP, Performance