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. [  Macros, Mixins, and Custom Collection Methods in Laravel ](#macros-mixins-and-custom-collection-methods-in-laravel)
2. [  How Macroable Works ](#how-codemacroablecode-works)
3. [  Grouping with Mixins ](#grouping-with-mixins)
4. [  Extending Request and Response ](#extending-request-and-response)
5. [  Testing Macros ](#testing-macros)
6. [  When Not to Use Macros ](#when-not-to-use-macros)
7. [  Takeaways ](#takeaways)

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

  #laravel   #collections   #macros   #php  

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

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

       Table of contents

1. [  01   Macros, Mixins, and Custom Collection Methods in Laravel  ](#macros-mixins-and-custom-collection-methods-in-laravel)
2. [  02   How Macroable Works  ](#how-codemacroablecode-works)
3. [  03   Grouping with Mixins  ](#grouping-with-mixins)
4. [  04   Extending Request and Response  ](#extending-request-and-response)
5. [  05   Testing Macros  ](#testing-macros)
6. [  06   When Not to Use Macros  ](#when-not-to-use-macros)
7. [  07   Takeaways  ](#takeaways)

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

Laravel's `Macroable` trait is one of the most underused extension points in the framework. Rather than subclassing `Collection`, `Request`, or `Response`, you can bolt on behaviour at boot time — keeping the framework's internals intact while making your application code read like a DSL.

### How `Macroable` Works

Any class using the `Macroable` trait gains two static methods: `macro()` and `mixin()`. When you call a macro, Laravel resolves it from a static array and invokes it bound to the current instance — so `$this` works exactly as you'd expect.

```php
use Illuminate\Support\Collection;

Collection::macro('toIndexedMap', function (string $key): array {
    return $this->keyBy($key)->map->toArray()->all();
});

// Usage
$users = collect([
    ['id' => 1, 'name' => 'Alice'],
    ['id' => 2, 'name' => 'Bob'],
]);

$map = $users->toIndexedMap('id');
// [1 => ['id' => 1, 'name' => 'Alice'], 2 => [...]]

```

Register macros inside a service provider's `boot()` method so they're available for the entire request lifecycle.

### Grouping with Mixins

Once you have more than a handful of macros, a mixin class keeps things tidy. A mixin is a plain class whose public methods each return a `Closure`. Laravel iterates those methods and registers each one as a macro.

```php
namespace App\Support\Mixins;

use Illuminate\Support\Collection;

class CollectionMixin
{
    public function paginateArray(): \Closure
    {
        return function (int $perPage, int $page = 1): array {
            return [
                'data'  => $this->forPage($page, $perPage)->values()->all(),
                'total' => $this->count(),
                'page'  => $page,
                'pages' => (int) ceil($this->count() / $perPage),
            ];
        };
    }

    public function mapToValueObjects(): \Closure
    {
        return function (string $class): static {
            return $this->map(fn ($item) => new $class($item));
        };
    }
}

```

```php
// AppServiceProvider::boot()
Collection::mixin(new \App\Support\Mixins\CollectionMixin());

```

IDE support is the usual concern. Add a `@mixin` annotation in a stub or use a package like `barryvdh/laravel-ide-helper` to generate PHPDoc for macros.

### Extending Request and Response

The same pattern applies beyond `Collection`. Extending `Request` is especially useful for multi-tenant apps where you repeatedly resolve the current tenant.

```php
use Illuminate\Http\Request;

Request::macro('tenant', function (): ?\App\Models\Tenant {
    return $this->attributes->get('tenant');
});

// In a middleware
$request->attributes->set('tenant', $resolvedTenant);

// In a controller
$tenant = $request->tenant();

```

No inheritance, no custom `FormRequest` base class — just a clean extension point registered once.

### Testing Macros

Because macros are registered globally, test them in isolation by calling the macro directly in a unit test. Pest makes this concise:

```php
use Illuminate\Support\Collection;

it('paginates an array correctly', function () {
    $result = collect(range(1, 25))->paginateArray(perPage: 10, page: 2);

    expect($result['data'])->toHaveCount(10)
        ->and($result['total'])->toBe(25)
        ->and($result['pages'])->toBe(3);
});

```

Register the mixin in a `beforeEach` or in a dedicated `TestCase` base if it isn't already booted by the application.

### When Not to Use Macros

- **Complex domain logic** — a dedicated service or action class is more testable and discoverable.
- **Overriding existing methods** — macros cannot override methods already defined on the class; they only add new ones.
- **Cross-cutting concerns with dependencies** — if your macro needs injected services, resolve them from the container inside the closure rather than relying on constructor injection.

### Takeaways

- Register macros in service provider `boot()` methods, never in `register()`.
- Use mixin classes to group related macros and keep providers lean.
- `$this` inside a macro closure is bound to the instance — use it freely.
- Add IDE stubs or `@mixin` annotations so static analysis tools stay happy.
- Prefer macros for *presentation and convenience* helpers; keep domain logic in dedicated classes.

 Found this useful?

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

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

  3 questions  

     Q01  Can a macro override an existing method on a Laravel class?        No. The `Macroable` trait only adds new methods. If a method already exists on the class, the macro is silently ignored. Use subclassing or decoration if you need to override existing behaviour. 

      Q02  How do I get IDE autocompletion for registered macros?        Add a `@mixin` PHPDoc annotation pointing to your mixin class, or use `barryvdh/laravel-ide-helper` which can generate `_ide_helper.php` stubs that include macro signatures for tools like PhpStorm. 

      Q03  Is there a performance cost to registering many macros?        Negligible. Macros are stored in a static array and resolved with a simple `isset` check. The cost is one closure allocation per macro at boot time, which is trivial compared to typical service container bindings. 

  Continue reading

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

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

 [ ![Advanced Authorization in Laravel: Gates, Policies, and Response-Based Access Control](https://cdn.msaied.com/571/e2c97418f4d543aac16e77c5dfd1055a.png) laravel authorization security 

### Advanced Authorization in Laravel: Gates, Policies, and Response-Based Access Control

Go beyond simple boolean gates. Learn how Laravel's response-based authorization lets you return rich denial r...

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

 20 Aug 2026     3 min read  

  Read    

 ](https://msaied.com/articles/advanced-authorization-in-laravel-gates-policies-and-response-based-access-control-4) [ ![Queue::forward(): Reroute Laravel Queues in One Place](https://cdn.msaied.com/572/c3ded57b390d88d1ceb9bd8570729835.png) Laravel Queues Laravel 13.26 

### Queue::forward(): Reroute Laravel Queues in One Place

Laravel 13.26 introduces Queue::forward(), letting you redirect any queue to a different name, connection, or...

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

 19 Aug 2026     3 min read  

  Read    

 ](https://msaied.com/articles/queueforward-reroute-laravel-queues-in-one-place) [ ![Laravel Tackle: Run an AI Coding Agent Inside Your Laravel Application](https://cdn.msaied.com/573/8f6b08a47a4bf04ae26b9f03d8e2e697.png) Laravel AI Artisan 

### Laravel Tackle: Run an AI Coding Agent Inside Your Laravel Application

Laravel Tackle brings an AI coding agent directly into your app as Artisan commands. It can read routes, query...

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

 19 Aug 2026     4 min read  

  Read    

 ](https://msaied.com/articles/laravel-tackle-run-an-ai-coding-agent-inside-your-laravel-application) 

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