Eloquent Macroable: Extending Models
Eloquent Macroable: Extending Models
Eloquent Macroable: Extending Models
Tip: Collection Macros
Collection::macro('toUpper', function () {
return $this->map(fn($v) => strtoupper($v));
});
collect(['a', 'b'])->toUpper(); // ['A', 'B']
Gotcha: Macros Are Global
Once registered, a macro is available everywhere. Use namespacing in macro names to avoid collisions.
Tip: Model Macros
Eloquent models are macroable too:
Post::macro('recent', function () {
return $this->where('created_at', '>', now()->subDays(7));
});
Gotcha: Macros Don't Have Access to $this Correctly
In macros, $this refers to the collection/model instance. But type hints won't work.
Tip: Mixin for Multiple Macros
Collection::mixin(new CollectionMacros());
Group related macros in a class.
Gotcha: Macro Registration Timing
Register macros in a service provider's boot() method, not register().
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
The Macroable trait is one of Laravel's most elegant extensibility mechanisms. I've used it to add toCsv() to collections, sendSlackNotification() to the Notification facade, and custom whereLike() to the query builder. The discipline I follow: macro only when the extension is genuinely framework-level. If the functionality is application-specific, it belongs in a dedicated service class, not a macro.
Source: Laravel Docs (https://laravel.com/docs/eloquent), Laravel News (https://laravel-news.com/), Freek.dev (https://freek.dev/tags/eloquent)