Revolutionize Laravel Development: Say Goodbye to Macros, Hello to Mixins!
Hello and welcome to our comprehensive guide on becoming an expert in using Mixins in Laravel! This guide is designed to enhance your Laravel development skills by delving deep into the realm of Mixins. But first, let’s briefly touch on Macros. Macros are a key aspect of Laravel that allow you to expand the capabilities of classes by adding custom methods. They play a vital role in developing reusable and organized code in Laravel, and I’ll show you how to make the most of them to create efficient and scalable applications. For example, you may want to include some custom methods in the Str
and Arr
helper classes of Laravel.
As an example, for Str
helper they can be
fullName
initials
As for Arr
helper class:
camelToSnake
snakeToCamel
filterNulls
For now, let’s add above methods inside of boot method of AppServiceProvider.php
by using macros.
<?php
namespace App\Providers;
use Illuminate\Support\Arr;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Str::macro('fullName', function (string $firstname, string $lastname) {
return trim($firstname . ' ' . $lastname);
});
Str::macro('initials', function (string $firstname, string $lastname) {
return strtoupper($firstname[0] . $lastname[0]);
});
Arr::macro('camelToSnake', function (array $array) {
return Arr::mapWithKeys($array, function ($value, $key) {
return [Str::snake($key) => $value];
});
});
Arr::macro('snakeToCamel', function (array $array) {
return Arr::mapWithKeys($array, function ($value, $key) {
return [Str::camel($key) => $value];
});
});
Arr::macro('filterNulls', function (array $array) {
return Arr::where($array, function ($value) {
return !is_null($value);
});
});
}
}
In Laravel, there are several classes that can be easily extended with custom methods, known as “Macroable” classes. Instead of cluttering the AppServiceProvider
with different macro methods for each class, you can create separate provider classes for each macroable class and register them in the config/app.php
file. However, this can be a bit cumbersome and messy, especially when keeping track of all the methods. I prefer a more native, readable, and maintainable approach. So, what can be done? This is where Mixins come in. By using Mixins, you can simplify the process of extending classes and make your code more organized and easier to manage.
What is a Mixin?
Similarly to Macro, a Mixin is a concept related to extending the functionality of existing classes in a broader Laravel context. Here’s a breakdown of how Mixin works:
A Mixin Class contains the methods you want to add to another class. These methods typically:
- Are either
public
orprotected
(private methods won't be registered as macros). - Don’t have any arguments (parameters).
- Return a
Closure
(anonymous function) that encapsulates the actual logic you want to add. The closure can have its own arguments though.
Now let’s create Mixins folder under app
directory of your Laravel project. And create StringMixin
and ArrayMixin
classes respectively.
Define your macro helpers as functions inside of them:
ArrayMixin.php
<?php
namespace App\Mixins;
use Closure;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
class ArrayMixin
{
/**
* @return Closure
*/
public function camelToSnake()
{
return function (array $array) {
return Arr::mapWithKeys($array, function ($value, $key) {
return [Str::snake($key) => $value];
});
};
}
/**
* @return Closure
*/
public function snakeToCamel()
{
return function (array $array) {
return Arr::mapWithKeys($array, function ($value, $key) {
return [Str::camel($key) => $value];
});
};
}
/**
* @return Closure
*/
public function filterNulls()
{
return function (array $array) {
return Arr::where($array, function ($value) {
return !is_null($value);
});
};
}
}
StringMixin.php
<?php
namespace App\Mixins;
use Closure;
class StringMixin
{
/**
* @return Closure
*/
public function fullName()
{
return function (string $firstname, string $lastname) {
return trim($firstname.' '.$lastname);
};
}
/**
* @return Closure
*/
public function initials()
{
return function (string $firstname, string $lastname) {
return strtoupper($firstname[0].$lastname[0]);
};
}
}
Now register these Mixins in AppServiceProvider
:
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Str::mixin(new StringMixin());
Arr::mixin(new ArrayMixin());
}
Great job! Now your project is nicely organized and the code is easier to read.
You can still use those helper methods in the same way as before, like Str::initials(...)
, Arr::filterNulls(...)
, etc.
ℹ️ If you notice a growing number of registrable mixins throughout your project, consider creating a new service provider named
MixinServiceProvider
and register it in your Laravel application.
Benefits of Mixins:
- Code Reusability: By encapsulating helper logic in a Mixin class, you can reuse it across different parts of your application without duplicating code.
- Code Cleanliness: Mixins help keep your original class code clean and focused on its core functionality. Helper methods are separated into a dedicated class.
- Improved Maintainability: If you ever need to modify or remove the helper logic, it’s all located in one place — the Mixin class.
See you in the next article.