DEV Community

Cover image for Macros & Mixins in Laravel and additional development features | Macroable
Denis Sinyukov
Denis Sinyukov

Posted on • Updated on • Originally published at coderden.dev

Macros & Mixins in Laravel and additional development features | Macroable

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 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.
Str::macro('toLower', fn($str) => strtolower($str));
Enter fullscreen mode Exit fullscreen mode
  1. The second way is to create a new service provider App\Providers\MacroableServiceProvider and register it in AppServiceProvider. For example,
class MacroableServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        // TODO
    }
}
Enter fullscreen mode Exit fullscreen mode
class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
       $this->app->register(MacroableServiceProvider::class);
    }
}

Enter fullscreen mode Exit fullscreen mode

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.

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!
);
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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.

public function boot(): void
{
    \Illuminate\Auth\RequestGuard::mixin(new class {

        public function loginUsingId(): \Closure
        {
            return function($id) {
                /** @var Authenticatable $loggedInUser */
                $loggedInUser = $this->authenticate();

                // TODO 
            };
        }
    });
}
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (1)

Collapse
 
wesllycode profile image
wesllycode

Very nice!