$ lexprog.com

// notes from an old coder -- php, databases, and the occasional rant

[September 27, 2025] Eloquent ORM

Eloquent Query Builder: Macros

Eloquent Query Builder: Macros

────────────────────────────────────────────────────────

Eloquent Query Builder: Macros

Tip: Register Macro

Builder::macro('published', function () {
    return $this->whereNotNull('published_at')->where('published', true);
});

Gotcha: Macro Availability

Macros are available on all query builder instances after registration.

Tip: Macro with Parameters

Builder::macro('recent', function ($days = 7) {
    return $this->where('created_at', '>=', now()->subDays($days));
});

Gotcha: Macro in Service Provider

Register macros in a service provider's boot() method.

Tip: Collection Macros

Collection::macro('toUpper', function () {
    return $this->map(fn($v) => strtoupper($v));
});

Gotcha: Macro Type Safety

Macros don't have type hints. Document parameters clearly.

Tip: Use cursor() for Memory-Neutral Iteration

When exporting 100K rows, get() loads everything into memory. cursor() uses yield and keeps memory flat regardless of row count. Perfect for artisan commands.

Tip: whereHas() vs load() — Two Different Things

whereHas() filters the parent query by relationship existence. load() eager-loads relationships AFTER the query. Mixing them up is a common source of logic bugs.

Gotcha: withCount() Adds a Subquery

withCount('comments') runs a correlated subquery on every row. On large tables, this can be slower than a separate query. Profile before relying on it.

Senior Insight

Eloquent performance is not about writing faster code — it's about writing fewer queries. Every relationship load, every attribute access, every serialization is potentially a database query. I always add Clockwork or Debugbar to my local environment and watch the query count on every page. A page that should make 5 queries but makes 50 has an N+1 problem that will only get worse with more data. Fix query counts before optimizing individual queries.

Source: Laravel Docs (https://laravel.com/docs/eloquent), Laravel News (https://laravel-news.com/), Freek.dev (https://freek.dev/tags/eloquent)

────────────────────────────────────────────────────────
<-- back to posts