Updated June 2026. Tested on Laravel 13 and PHP 8.4.
Many of Laravel's core classes are "macroable", which means you can bolt your own methods onto them at runtime without touching the framework. The query builder, collections, requests, responses and more all support this. It is a clean way to package a bit of logic you reuse, and then call it like it was built in.
You register macros in the boot method of a service provider, so they are available everywhere.
A query builder macro
Suppose you keep writing the same active and recent filter on different models. Wrap it in a builder macro once.
use Illuminate\Database\Eloquent\Builder;
public function boot(): void
{
Builder::macro('activeRecent', function () {
return $this->where('is_active', true)->latest();
});
}
Now any Eloquent query can call it.
$posts = Post::activeRecent()->get();
$users = User::activeRecent()->limit(5)->get();
Inside the macro, $this is the query builder, so you chain the normal methods. This reads better than repeating the same where and latest everywhere, and if the definition of "active recent" changes, you fix it in one place.
A collection macro
Collections are macroable too. Say you often want to turn a collection into a comma separated string of a field.
use Illuminate\Support\Collection;
public function boot(): void
{
Collection::macro('toCsv', function (string $field) {
return $this->pluck($field)->implode(', ');
});
}
$names = User::all()->toCsv('name'); // "Jane, Akram, Sam"
A response macro
A common one is a standard JSON shape for your API, so every endpoint answers the same way.
use Illuminate\Support\Facades\Response;
public function boot(): void
{
Response::macro('success', function ($data, string $message = 'OK') {
return Response::json([
'message' => $message,
'data' => $data,
]);
});
}
return response()->success($user, 'User created');
Where macros fit
Macros shine for small, cross cutting helpers you want available on a core class. For anything bigger, a dedicated class, a trait, or a query scope is usually clearer. But for that one method you keep wishing the builder or a collection had, a macro is the neat answer, and it keeps the call site looking like first class Laravel. Questions welcome in the comments.
All comments ()
No comments yet
Be the first to leave a comment on this post.