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. [  Macros: One-Off Extensions ](#macros-one-off-extensions)
3. [  Mixins: Grouping Related Macros ](#mixins-grouping-related-macros)
4. [  Custom Collection Classes: When Macros Aren't Enough ](#custom-collection-classes-when-macros-arent-enough)
5. [  Organising Registration: Avoid the God Provider ](#organising-registration-avoid-the-god-provider)
6. [  Key Takeaways ](#key-takeaways)

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

  #laravel   #collections   #macros   #php  

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

     20 Jun 2026      3 min read    ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said  

       Table of contents

1. [  01   Extending Laravel Without Forking It  ](#extending-laravel-without-forking-it)
2. [  02   Macros: One-Off Extensions  ](#macros-one-off-extensions)
3. [  03   Mixins: Grouping Related Macros  ](#mixins-grouping-related-macros)
4. [  04   Custom Collection Classes: When Macros Aren't Enough  ](#custom-collection-classes-when-macros-arent-enough)
5. [  05   Organising Registration: Avoid the God Provider  ](#organising-registration-avoid-the-god-provider)
6. [  06   Key Takeaways  ](#key-takeaways)

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

Laravel ships with a `Macroable` trait that lets you bolt new methods onto core classes at runtime. Used carelessly, this becomes a dumping ground in `AppServiceProvider`. Used well, it's a clean extension point that keeps your domain vocabulary inside the framework's fluent API.

This article covers three distinct patterns: standalone macros, mixin classes, and purpose-built Collection methods — with concrete examples and the tradeoffs of each.

---

Macros: One-Off Extensions
--------------------------

The `Macroable` trait is used by `Collection`, `Builder`, `Request`, `Response`, `Str`, `Arr`, and more. Registering a macro is straightforward:

```php
use Illuminate\Support\Collection;

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

// Usage
$map = collect($rows)->toAssoc('id', 'name');

```

Inside the closure, `$this` is bound to the macro's host object, so you get full access to its public and protected API. PHPStan and IDE plugins won't know about it by default — address that with a `@method` annotation on a stub or a dedicated `_ide_helper_macros.php` file.

---

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

When you have five or more related macros, a mixin class keeps them cohesive and testable:

```php
namespace App\Support\Mixins;

class CollectionMixin
{
    public function toAssoc(): \Closure
    {
        return function (string $keyField, string $valueField): array {
            return $this->mapWithKeys(
                fn ($item) => [$item[$keyField] => $item[$valueField]]
            )->all();
        };
    }

    public function groupByFirst(): \Closure
    {
        return function (string $key): self {
            return $this->groupBy(fn ($item) => $item[$key] ?? null);
        };
    }
}

```

Register the mixin once, typically in a focused service provider:

```php
use Illuminate\Support\Collection;
use App\Support\Mixins\CollectionMixin;

Collection::mixin(new CollectionMixin());

```

`mixin()` reflects over every public method, calls it to retrieve the closure, and registers each as a macro. The result is identical to registering macros individually, but the code is organised and unit-testable in isolation.

---

Custom Collection Classes: When Macros Aren't Enough
----------------------------------------------------

For domain-specific pipelines, a typed custom collection beats macros every time. You get return-type safety, IDE completion, and no global side effects:

```php
namespace App\Domain\Billing\Collections;

use Illuminate\Support\Collection;
use App\Domain\Billing\ValueObjects\Money;

/**
 * @extends Collection
 */
class InvoiceCollection extends Collection
{
    public function totalDue(): Money
    {
        return Money::ofMinorUnits(
            $this->sum(fn ($invoice) => $invoice->amount_due_cents)
        );
    }

    public function overdue(): static
    {
        return $this->filter(
            fn ($invoice) => $invoice->due_at->isPast() && ! $invoice->paid
        );
    }
}

```

Wire it to your Eloquent model so `get()` and `all()` return the typed collection automatically:

```php
class Invoice extends Model
{
    public function newCollection(array $models = []): InvoiceCollection
    {
        return new InvoiceCollection($models);
    }
}

```

Now `Invoice::where('user_id', $id)->get()` returns an `InvoiceCollection`, and `->totalDue()` is fully typed.

---

Organising Registration: Avoid the God Provider
-----------------------------------------------

Don't pile macros into `AppServiceProvider`. Instead:

1. Create a `MacroServiceProvider` per domain or package.
2. Register it in `bootstrap/providers.php` (Laravel 11+) or `config/app.php`.
3. Keep each mixin class in `app/Support/Mixins/` or inside the relevant domain folder.

```php
// app/Providers/BillingMacroServiceProvider.php
public function boot(): void
{
    Collection::mixin(new CollectionMixin());
    Request::mixin(new RequestMixin());
}

```

This makes it trivial to extract a domain into a package later — the service provider and mixin classes move together.

---

Key Takeaways
-------------

- Use **standalone macros** for one-off, cross-cutting helpers.
- Use **mixin classes** when you have a cohesive group of related extensions; they're unit-testable and self-documenting.
- Use **custom Collection subclasses** for domain-specific pipelines where return-type safety matters.
- Register macros in **dedicated service providers**, not `AppServiceProvider`.
- Generate IDE helper stubs (`php artisan ide-helper:generate`) or maintain `@method` annotations so static analysis tools stay accurate.

 Found this useful?

          [  ](https://twitter.com/intent/tweet?url=https%3A%2F%2Fmsaied.com%2Farticles%2Fmacros-mixins-and-custom-collection-methods-in-laravel&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) 

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

  3 questions  

     Q01  Can I use macros on classes that don't use the Macroable trait?        No. Only classes that include the `Macroable` trait support `::macro()` and `::mixin()`. If you need to extend a non-macroable class, subclass it or use a decorator 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-lived workers. Register them once in a service provider's `boot()` method and they remain available for the lifetime of the worker process. 

      Q03  When should I prefer a custom Collection subclass over a mixin?        Prefer a subclass when the methods are domain-specific, return typed values, or only make sense for a particular model. Mixins are better for generic, reusable helpers that apply across many collection types. 

  Continue reading

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

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

 [ ![Laravel AI SDK: Tool-Calling Agents and Conversation Persistence](https://cdn.msaied.com/260/8c84f424e42da01993c9ba4b8eb19655.png) laravel ai agents 

### Laravel AI SDK: Tool-Calling Agents and Conversation Persistence

Build reliable tool-calling AI agents in Laravel using the Prism package. Learn how to wire tools, persist con...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 21 Jun 2026     3 min read  

  Read    

 ](https://msaied.com/articles/laravel-ai-sdk-tool-calling-agents-and-conversation-persistence) [ ![Laravel Livewire v3 Internals: Morph Markers, JS Hooks, and Alpine Integration](https://cdn.msaied.com/259/e8ce445f021c2b26ebe4dd5da50014f8.png) livewire laravel alpine 

### Laravel Livewire v3 Internals: Morph Markers, JS Hooks, and Alpine Integration

Go beyond the docs: understand how Livewire v3 diffs the DOM with morph markers, intercept the lifecycle with...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 21 Jun 2026     3 min read  

  Read    

 ](https://msaied.com/articles/laravel-livewire-v3-internals-morph-markers-js-hooks-and-alpine-integration) [ ![Laravel Package Development: Service Providers, Auto-Discovery, and Config Merging](https://cdn.msaied.com/258/673a80fa8e42ae375a4bba21bdcd92ea.png) laravel packages service-providers 

### Laravel Package Development: Service Providers, Auto-Discovery, and Config Merging

Build a production-ready Laravel package from scratch — covering service provider design, auto-discovery via c...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 21 Jun 2026     3 min read  

  Read    

 ](https://msaied.com/articles/laravel-package-development-service-providers-auto-discovery-and-config-merging-1) 

   [  ![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)
