Laravel Macroable: Understanding macros and mixin
Published: 2023-12-14 09:02:17


**Laravel Macroable**, a powerful package, enables developers to augment a class's functionality dynamically, bridging the gap in its definition through a straightforward trait. Importantly, this capability extends beyond Laravel's internal classes, allowing any class utilizing Illuminate\Support\Traits\Macroable to expand its capabilities.

## How to Use Laravel Macroable
If you're not using Laravel, the first step is to install the package:

`bash
composer require illuminate/macroable`
Include the autoload.php file from the vendor directory in your codebase.

Now, let's define a class with the Macroable trait:

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

class Greeting
{
    use Macroable;
    public function __construct(protected string $name)
    {
    }
    public function sayHello()
    {
        return sprintf('Hello %s%s', $this->name, PHP_EOL);
    }
}`
To extend functionality, use the macro method in your codebase:

`php
Greeting::macro('greet', function (?string $greeting = null) {
    return !is_null($greeting)
        ? sprintf('%s %s%s', $greeting, $this->name, PHP_EOL)
        : $this->sayHello();
});`
Now, you can call the newly added method:

`php
$greeting = new Greeting('Anik');
echo $greeting->sayHello();           // "Hello Anik"
echo $greeting->greet('Good evening'); // "Good evening Anik"
echo $greeting->greet('Goodbye');      // "Goodbye Anik"
echo $greeting->greet();               // "Hello Anik"`

## Static Method Usage
You can also call macros as static methods:

`php
Greeting::macro('whatTimeIsIt', function () {
    return sprintf(
        'Hey, it is %s',
        (new DateTimeImmutable())->format('H:i:s')
    );
});

echo Greeting::whatTimeIsIt(); // "Hey, it is 07:02:01"`
A method added through macros can be invoked from both class and object contexts, providing flexibility based on the calling context.

## Understanding Mixins

While ::macro works for adding individual methods, it can become unwieldy for multiple additions. Enter mixins. A mixin lets you include all methods from a designated class.

First, define a class holding the extended functionality:

`php
<?php
class GreetingMixin
{
    public function greet()
    {
        return function (?string $greeting = null) {
            return $greeting 
               ? sprintf('%s %s%s', $greeting, $this->name, PHP_EOL)
               : $this->sayHello();
        };
    }
    public function whatTimeIsIt()
    {
        return function () {
            return sprintf(
                'Hey, it is %s',
                (new DateTimeImmutable())->format('H:i:s')
            );
        };
    }
}`
Now, connect the mixin to the Greeting class:

`php
Greeting::mixin(new GreetingMixin());`
Now, you can call these methods just like before:

`php
$greeting = new Greeting('Anik');

echo $greeting->sayHello();           // "Hello Anik"
echo $greeting->greet('Good evening'); // "Good evening Anik"
echo $greeting->greet('Goodbye');      // "Goodbye Anik"
echo $greeting->greet();               // "Hello Anik"

echo Greeting::whatTimeIsIt();         // "Hey, it is 07:02:01"`

## Where to Define Macros
In Laravel, you can define macros anywhere, but for good practice, consider placing them in a service provider. The AppServiceProvider is a suitable starting point for limited macros. For extensive macros, create a new provider like AdditionalMacroServiceProvider and add them in the boot method.

By understanding macros and mixins, developers can enhance the extensibility of their classes dynamically, adding new methods seamlessly and maintaining a clean and organized codebase.

Interested in **[custom software development](https://bachasoftware.com/services/custom-software-development)**? We’re **[HERE](Interested in development team ondemand? We’re HERE to help!)** to help!