Macros & Mixins in Laravel and additional development features | Macroable
Tags: laravel, webdev, php
Published: 2023-10-29 21:01:42

One of the features of Laravel is the ability to extend functionality through custom methods thanks to a concept called "macros". 

In this article, we will look at what they are, how to create them, and how they can improve our development.

## Understanding Macros

A macro is the injection of custom code into the core of a framework, without the need for complex inheritance or modification. 

To implement macros we use the [Macroable](https://laravel.com/api/10.x/Illuminate/Support/Traits/Macroable.html) trait, which has two main methods `macro()` and `mixin()`. 

The point is that by using PHP's magic methods `__call` and `__callStatic`, we add additional methods to existing application classes at runtime without changing the core.

## Advantages of macros and mixins

- **Code reuse**: By encapsulating custom logic in macros, you can apply it to different parts of your project without duplicating code.

- **Code cleanliness**: Macros help keep your code clean and user-friendly by bringing logic into separate service classes.

- **Improved performance**: Macros allow you to extend Laravel core functionality more efficiently and maintain compatibility with future framework updates, reducing implementation time.

## Creating Macro & Where should I define them?

1. It is a good idea to add this to the `App\Providers\AppServiceProvider` method in the `boot()` method, since it is called after all other service providers are registered and you have access to all other services. 

```php.
Str::macro('toLower', fn($str) => strtolower($str));
```

2. The second way is to create a new service provider `App\Providers\MacroableServiceProvider` and register it in AppServiceProvider. For example,

```php
class MacroableServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        // TODO
    }
}
```

```php
class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
       $this->app->register(MacroableServiceProvider::class);
    }
}

```
Macros can be defined in any class that defines `Macroable`. The framework provides the ability to extend the capabilities of a large number of classes. 

> Proprietary classes also have this capability, just add a few lines of code.

```php
use Illuminate\Support\Traits\Macroable;

$class = new class {
    use Macroable;

    public function hello()
    {
        return 'world';
    }
};

$class::macro('hey', fn() => 'girl!');

dd(
    $class->hello(), // world
    $class->hey(), // girl!
);
```
Below is a list of popular classes from Laravel core that utilize the concept of macros:

```
Illuminate\Http\Request
Illuminate\Http\Response
Illuminate\Support\Arr
Illuminate\Support\Collection
Illuminate\Support\Str
Illuminate\Routing\Router
Illuminate\Validation\Rule
Illuminate\Database\Query\Builder
```
> The list is not complete. You can use the project search with the keyword `use Macroable` to find more.

## Mixin & Strong Macro

The concept of macros allows multiple user-defined functions to be registered at once via a mixin class. Each method of which must return a closure. The name of the method acts as the name of the macro.

Registration of mixins is done in the same way as with a macro, using the `mixin()` method from the base class.

Let's look at the user authentication rule extension for an example.
```php
public function boot(): void
{
    \Illuminate\Auth\RequestGuard::mixin(new class {

        public function loginUsingId(): \Closure
        {
            return function($id) {
                /** @var Authenticatable $loggedInUser */
                $loggedInUser = $this->authenticate();
              
                // TODO 
            };
        }
    });
}
```
Grouping macros into separate classes, according to some principles, will help to understand the project more easily and make it easier to mashup.

## Conclusion

Whether you are building a small website or a complex web application, Laravel macros can be a valuable addition to a developer's toolkit.