Laravel Macros, Mixins &amp; Custom Collections | Mohamed Said        [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://msaied.com) [ Home ](https://msaied.com) [ Projects ](https://msaied.com/projects) [ Articles  ](https://msaied.com/articles) [ Certificates ](https://msaied.com/certificates) [ Contact ](https://msaied.com#contact-section) 

       [  ](https://github.com/EG-Mohamed)       

 [ Home ](https://msaied.com) [ Projects ](https://msaied.com/projects) [ Articles ](https://msaied.com/articles) [ Certificates ](https://msaied.com/certificates) [ Contact ](https://msaied.com#contact-section) 

  [ home ](https://msaied.com)    [ articles ](https://msaied.com/articles)    Macros, Mixins, and Custom Collection Methods in Laravel        On this page       1. [  Extending Laravel Without Forking It ](#extending-laravel-without-forking-it)
2. [  How Macroable Works ](#how-codemacroablecode-works)
3. [  Registering Macros the Right Way ](#registering-macros-the-right-way)
4. [  Mixins: Grouping Related Macros ](#mixins-grouping-related-macros)
5. [  IDE Support: Don't Skip This ](#ide-support-dont-skip-this)
6. [  Beyond Collections: Other Macroable Classes ](#beyond-collections-other-macroable-classes)
7. [  When Not to Use Macros ](#when-not-to-use-macros)
8. [  Takeaways ](#takeaways)

  ![Macros, Mixins, and Custom Collection Methods in Laravel](https://cdn.msaied.com/663/b8e39b17d427358aa43b5c3e8c1be908.png)

  #laravel   #collections   #macros   #php  

 Macros, Mixins, and Custom Collection Methods in Laravel 
==========================================================

     13 Sep 2026      4 min read    ![Mohamed Said](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp)  Mohamed Said  

       Table of contents

1. [  01   Extending Laravel Without Forking It  ](#extending-laravel-without-forking-it)
2. [  02   How Macroable Works  ](#how-codemacroablecode-works)
3. [  03   Registering Macros the Right Way  ](#registering-macros-the-right-way)
4. [  04   Mixins: Grouping Related Macros  ](#mixins-grouping-related-macros)
5. [  05   IDE Support: Don't Skip This  ](#ide-support-dont-skip-this)
6. [  06   Beyond Collections: Other Macroable Classes  ](#beyond-collections-other-macroable-classes)
7. [  07   When Not to Use Macros  ](#when-not-to-use-macros)
8. [  08   Takeaways  ](#takeaways)

 Extending Laravel Without Forking It
------------------------------------

Laravel ships with a `Macroable` trait that lets you bolt new behaviour onto core classes at runtime. Used well, it keeps domain language inside your codebase rather than scattered across helper files. Used carelessly, it turns a clean project into a maze of invisible methods. This article covers the mechanics, the guardrails, and the patterns that actually hold up at scale.

---

How `Macroable` Works
---------------------

Any class that uses `Illuminate\Support\Traits\Macroable` gains two static methods: `macro()` and `mixin()`. At call time, `__call` and `__callStatic` proxy to the registered closure.

```php
use Illuminate\Support\Collection;

Collection::macro('toAssoc', function (string $key, string $value): Collection {
    /** @var Collection $this */
    return $this->mapWithKeys(fn ($item) => [$item[$key] => $item[$value]]);
});

$result = collect([
    ['code' => 'USD', 'label' => 'US Dollar'],
    ['code' => 'EUR', 'label' => 'Euro'],
])->toAssoc('code', 'label');
// ['USD' => 'US Dollar', 'EUR' => 'Euro']

```

Inside the closure, `$this` is bound to the current collection instance, so you have full access to `$this->items` and every existing method.

---

Registering Macros the Right Way
--------------------------------

Never register macros in a controller or a model. Always use a **service provider** so the macro is available on every request before any consumer needs it.

```php
// app/Providers/CollectionMacroServiceProvider.php

namespace App\Providers;

use Illuminate\Support\Collection;
use Illuminate\Support\ServiceProvider;

class CollectionMacroServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Collection::macro('second', function (): mixed {
            return $this->skip(1)->first();
        });

        Collection::macro('mapToModel', function (string $class): Collection {
            return $this->map(fn ($data) => new $class($data));
        });
    }
}

```

Add it to `bootstrap/providers.php` (Laravel 11+) or `config/app.php` providers array.

---

Mixins: Grouping Related Macros
-------------------------------

When you have a family of related methods, a **mixin class** is cleaner than a long list of `macro()` calls. Each public method on the mixin class returns a closure that becomes a macro.

```php
// app/Mixins/CollectionCurrencyMixin.php

namespace App\Mixins;

use Illuminate\Support\Collection;

class CollectionCurrencyMixin
{
    public function sumMoney(): \Closure
    {
        return function (string $field, int $scale = 2): string {
            /** @var Collection $this */
            $total = $this->sum(fn ($item) => (int) round($item[$field] * (10 ** $scale)));
            return number_format($total / (10 ** $scale), $scale);
        };
    }

    public function formatAmounts(): \Closure
    {
        return function (string $field, string $currency = 'USD'): Collection {
            /** @var Collection $this */
            return $this->map(function ($item) use ($field, $currency) {
                $item[$field . '_formatted'] = $currency . ' ' . number_format($item[$field], 2);
                return $item;
            });
        };
    }
}

```

```php
// In your service provider boot()
Collection::mixin(new CollectionCurrencyMixin());

```

---

IDE Support: Don't Skip This
----------------------------

Macros are invisible to static analysis. Add a `@mixin` docblock or generate an `_ide_helper_macros.php` file with `barryvdh/laravel-ide-helper`. For Psalm/PHPStan, create a stub:

```php
// stubs/CollectionMacros.php  (excluded from autoload)

/** @mixin \Illuminate\Support\Collection */
class CollectionMacroStub
{
    public function toAssoc(string $key, string $value): \Illuminate\Support\Collection {}
    public function second(): mixed {}
}

```

Point your `phpstan.neon` at the stubs directory. Now your CI pipeline catches misuse.

---

Beyond Collections: Other Macroable Classes
-------------------------------------------

`Request`, `Response`, `Builder` (query builder), `Router`, `Str`, `Arr`, and `Carbon` (via `CarbonMixin`) all support macros. A practical example — adding a typed helper to the query builder:

```php
use Illuminate\Database\Query\Builder;

Builder::macro('whereUuid', function (string $column, string $uuid): Builder {
    /** @var Builder $this */
    return $this->where($column, '=', $uuid);
});

// Usage
User::query()->whereUuid('id', $request->uuid)->firstOrFail();

```

---

When Not to Use Macros
----------------------

- **Complex logic with dependencies** — inject a service instead; closures can't receive constructor injection cleanly.
- **Methods that need to be overridden per model** — use a custom base model or a trait.
- **Anything that should be tested in isolation** — macros are global state; prefer explicit classes for domain-critical logic.

---

Takeaways
---------

- Register all macros in a dedicated service provider, never inline.
- Use mixin classes to group related macros and keep providers readable.
- Add IDE stubs or `@mixin` annotations — macros without static analysis support create invisible debt.
- `Macroable` is available on `Request`, `Builder`, `Str`, `Router`, and more, not just `Collection`.
- Macros are global state; reserve them for genuinely cross-cutting, stateless helpers.

 Found this useful?

          [  ](https://twitter.com/intent/tweet?url=https%3A%2F%2Fmsaied.com%2Farticles%2Fmacros-mixins-and-custom-collection-methods-in-laravel-2&text=Macros%2C+Mixins%2C+and+Custom+Collection+Methods+in+Laravel) [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fmsaied.com%2Farticles%2Fmacros-mixins-and-custom-collection-methods-in-laravel-2) 

 Frequently Asked Questions 
----------------------------

  3 questions  

     Q01  Can I use dependency injection inside a Collection macro closure?        Not directly via constructor injection. You can call `app(MyService::class)` inside the closure, but if the logic is complex enough to need a service, extract it into a dedicated class and call that from the macro instead. 

      Q02  Do macros survive between Octane requests?        Yes — macros are registered on the class itself (stored in a static array), so they persist across requests in long-running processes like Octane. Register them once in a service provider and they remain available for the lifetime of the worker. 

      Q03  What is the difference between a macro and a mixin in Laravel?        A macro registers a single named closure on a Macroable class. A mixin registers all public methods of a class as macros in one call, which is cleaner when you have a family of related helpers to add. 

  Continue reading

 More Articles 
---------------

 [ View all    ](https://msaied.com/articles) 

 [ ![Modular Monolith in Laravel: Enforcing Bounded Contexts with Module Service Providers](https://cdn.msaied.com/662/7f9c800590e5d7c07197293837cf0114.png) laravel architecture modular-monolith 

### Modular Monolith in Laravel: Enforcing Bounded Contexts with Module Service Providers

Learn how to carve a Laravel application into cohesive bounded contexts using per-module service providers, ex...

  ![Mohamed Said](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp)  Mohamed Said 

 12 Sep 2026     3 min read  

  Read    

 ](https://msaied.com/articles/modular-monolith-in-laravel-enforcing-bounded-contexts-with-module-service-providers) [ ![Filament v4 Table Bulk Actions: Custom Confirmation Modals and Scoped Authorization](https://cdn.msaied.com/661/5f319b485f1bc0c76e2c82746f730c8c.png) filament laravel authorization 

### Filament v4 Table Bulk Actions: Custom Confirmation Modals and Scoped Authorization

Go beyond the default delete bulk action. Learn how to build custom Filament v4 bulk actions with typed confir...

  ![Mohamed Said](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp)  Mohamed Said 

 12 Sep 2026     4 min read  

  Read    

 ](https://msaied.com/articles/filament-v4-table-bulk-actions-custom-confirmation-modals-and-scoped-authorization) [ ![Laravel Horizon: Queue Metrics, Supervisor Tuning, and Safe Deployments](https://cdn.msaied.com/660/4e7fb1097d66f5b5c6bb68e5aad9b211.png) laravel horizon queues 

### Laravel Horizon: Queue Metrics, Supervisor Tuning, and Safe Deployments

Beyond the dashboard: how to use Horizon's metrics API, tune supervisor processes for mixed workloads, and dep...

  ![Mohamed Said](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp)  Mohamed Said 

 12 Sep 2026     3 min read  

  Read    

 ](https://msaied.com/articles/laravel-horizon-queue-metrics-supervisor-tuning-and-safe-deployments) 

   [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://msaied.com)Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

Explore

- [Home](https://msaied.com)
- [Projects](https://msaied.com/projects)
- [Articles](https://msaied.com/articles)
- [Certificates](https://msaied.com/certificates)
- [Contact](https://msaied.com#contact-section)

Connect

- [   hello@msaied.com ](mailto:hello@msaied.com)
- [   +20 109 461 9204 ](tel:+201094619204)

© 2026 Mohamed Said. All rights reserved.

 [  ](https://github.com/EG-Mohamed) [  ](https://www.linkedin.com/in/msaiedm/) [  ](https://wa.me/201094619204) [  ](mailto:hello@msaied.com) [  ](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
