Hey artisan, in this tutorial we are going to learn about laravel macros. Macro
is the powerful feature of the laravel framework. Macros allow you to add on custom functionality to internal Laravel components. This laravel macro also work with laravel 5.8 , 5.7 and 5.6 .
Macros provide a way to add functionality to the classes in which you don’t have that function. It helps you to create a small reusable component that will be possible to use it anywhere in your application.
In this post, we will be looking at how we can use Laravel Macros and which classes can be used to define macros.
In simple word, Laravel Macro is a way to add some missing functionality to Laravel’s internal component with a piece of code which doesn’t exist in the Laravel class. To implement a Laravel Macro, Laravel provides a PHP trait called Macroable.
You can check for example Response class of Laravel locating at Illuminate\Http\Response
which implements the Macroable
trait, which means you can extend the Response class using a Macro.
The following Laravel’s classes allow for macros to be created by using the Illuminate\Support\Traits\Macroable trait. Here are some of the most commonly used classes to create macros.
There other classes and facades which use the Macroable
trait. You can find all the classes and facades in the codebase of Laravel.
Example of a Laravel Macro
Before creating a Laravel Macro, you have to make sure your targeted class use the Macroable trait. Here we will be creating a macro on Illuminate\Support\Str class which will check the length of a given string named isLength
. You can define the macro in your AppServiceProvider class’s boot()
method.
app/Providers/AppServiceProvider.php
namespace App\Providers;
use Illuminate\Support\Str;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Str::macro('isLength', function ($str, $length) {
return static::length($str) == $length;
});
}
}
Within the boot method of AppServiceProvider, we are defining a isLength
macro on Str
class which simply compare the length of first parameter with second one.
Macros can have a number of parameters that you decide. It’s important to note that we are calling static::length
in the macro, as macros still have full access to methods on the original class.
Now you can use this macro anywhere in your application.
use Illuminate\Support\Str;
Route::get('/', function(){
dd(Str::isLength('This is a Laravel Macro', 23)); //true
});
The Macroable trait’s internal mechanisms allow macros to be called from both static and instance contexts.
Creating Mutliple Macros
We have added two macros to the Str class using the AppServiceProvider. But as soon as your application will start growing, your AppServiceProvider will start becoming messy. From Laravel 5.5 onward, we can define class based macros which will make our code less messy.
We will continue with our previous example and move our two macros into a new class. We will create a new class called StrMixin and store it in app/Mixins
folder.
App\Mixins\StrMixin.php
namespace App\Mixins;
class StrMixin
{
/**
* @return \Closure
*/
public function isLength()
{
return function($str, $length) {
return static::length($str) == $length;
};
}
/**
* @return \Closure
*/
public function appendTo()
{
return function($str, $char) {
return $char.$str;
};
}
}
Now in your AppServiceProvider, you can remove the previous macros declaration. We can use mixin()
method to initialize all your macros for a given class. Your AppServiceProvider will look like below after making modifications.
app/Providers/AppServiceProvider.php
namespace App\Providers;
use App\Mixins\StrMixin;
use Illuminate\Support\Str;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Str::mixin(new StrMixin);
}
}
Now if you test isLength()
and appendTo()
method on Str
class, you will have the same results. Now you know how to extend the Laravel’s core classes using Laravel Macros. Hope it will help you.