
We all know that Laravel has many features that we not even see in other frameworks. One of the most powerful feature is Macro. Macro allow us to add new custom functionality to internal Laravel Component and custom services and classes. If I simply the term Macro allow us to extends the Laravel Classes. Now we will see How to use Macro in Laravel?

How to use Macro in Laravel?
There are different ways to use Macro in Laravel Project but we will see the simplest solution that you can easily understand and try in your project ASAP.
First we will see that how we can add new functionality in existing Laravel components.
We giving a list that can use macro and easily to extends the Laravel Classes.
- Illuminate\Auth\RequestGuard
- Illuminate\Auth\SessionGuard
- Illuminate\Cache\Repository
- Illuminate\Console\Command
- Illuminate\Console\Scheduling\Event
- Illuminate\Cookie\CookieJar
- Illuminate\Database\Eloquent\FactoryBuilder
- Illuminate\Database\Eloquent\Relations\Relation
- Illuminate\Database\Grammar
- Illuminate\Database\Query\Builder
- Illuminate\Database\Schema\Blueprint
- Illuminate\Filesystem\Filesystem
- Illuminate\Foundation\Testing\TestResponse
- Illuminate\Http\JsonResponse
- Illuminate\Http\RedirectResponse
- Illuminate\Http\Request
- Illuminate\Http\Response
- Illuminate\Http\UploadedFile
- Illuminate\Mail\Mailer
- Illuminate\Routing\PendingResourceRegistration
- Illuminate\Routing\Redirector
- Illuminate\Routing\ResponseFactory
- Illuminate\Routing\Route
- Illuminate\Routing\Router
- Illuminate\Routing\UrlGenerator
- Illuminate\Support\Arr
- Illuminate\Support\Collection
- Illuminate\Support\LazyCollection
- Illuminate\Support\Str
- Illuminate\Support\Testing\Fakes\NotificationFake
- Illuminate\Translation\Translator
- Illuminate\Validation\Rule
- Illuminate\View\Factory
- Illuminate\View\View
Here we take some example to extends Laravel Functionality.
Symlink Laravel Storage Folder on Shared Hosting
We add some code in boot()
method of App\Providers\AppServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Http\Request;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Str::macro("checkLength", function (string $str, int $length) {
return static::length($str) === $length;
});
}
}
Now we have new custom method named checkLength()
that accept two arguments on method call.
Lets check how we use checkLength()
method. Here we use closure function in routes.
<?php
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
\Illuminate\Support\Str::checkLength("This is Test", 12); // return true if length match
});
We can use custom functionality where Macroable trait used. So first we take a look at trait .
Macroable Trait
Macroable trait is responsible to extends Laravel and Custom classes functionality where we or Laravel Core uses Macroable trait.
Lets see the Str class first.
Illuminate\Support\Str.php
<?php
namespace Illuminate\Support;
use Illuminate\Support\Traits\Macroable;
use League\CommonMark\GithubFlavoredMarkdownConverter;
use Ramsey\Uuid\Codec\TimestampFirstCombCodec;
use Ramsey\Uuid\Generator\CombGenerator;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidFactory;
use voku\helper\ASCII;
class Str
{
use Macroable;
.........
}
Now Have a look at Macroable Trait.
Illuminate\Support\Traits\Macroable.php
<?php
namespace Illuminate\Support\Traits;
use BadMethodCallException;
use Closure;
use ReflectionClass;
use ReflectionMethod;
trait Macroable
{
/**
* The registered string macros.
*
* @var array
*/
protected static $macros = [];
/**
* Register a custom macro.
*
* @param string $name
* @param object|callable $macro
* @return void
*/
public static function macro($name, $macro)
{
static::$macros[$name] = $macro;
}
/**
* Mix another object into the class.
*
* @param object $mixin
* @param bool $replace
* @return void
*
* @throws \ReflectionException
*/
public static function mixin($mixin, $replace = true)
{
$methods = (new ReflectionClass($mixin))->getMethods(
ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED
);
foreach ($methods as $method) {
if ($replace || ! static::hasMacro($method->name)) {
$method->setAccessible(true);
static::macro($method->name, $method->invoke($mixin));
}
}
}
/**
* Checks if macro is registered.
*
* @param string $name
* @return bool
*/
public static function hasMacro($name)
{
return isset(static::$macros[$name]);
}
/**
* Dynamically handle calls to the class.
*
* @param string $method
* @param array $parameters
* @return mixed
*
* @throws \BadMethodCallException
*/
public static function __callStatic($method, $parameters)
{
if (! static::hasMacro($method)) {
throw new BadMethodCallException(sprintf(
'Method %s::%s does not exist.', static::class, $method
));
}
$macro = static::$macros[$method];
if ($macro instanceof Closure) {
$macro = $macro->bindTo(null, static::class);
}
return $macro(...$parameters);
}
/**
* Dynamically handle calls to the class.
*
* @param string $method
* @param array $parameters
* @return mixed
*
* @throws \BadMethodCallException
*/
public function __call($method, $parameters)
{
if (! static::hasMacro($method)) {
throw new BadMethodCallException(sprintf(
'Method %s::%s does not exist.', static::class, $method
));
}
$macro = static::$macros[$method];
if ($macro instanceof Closure) {
$macro = $macro->bindTo($this, static::class);
}
return $macro(...$parameters);
}
}
We already used macro()
method that provided by Macroable
trait. Now we take a look on mixin()
method.
When we have to add multiple functionality to a Laravel Component we use mixin()
.
Lets take example.
First we create a custom class that have some methods because mixin()
except a object.
App\Macro\StringMacro.php
<?php
namespace App\Macro;
use Illuminate\Support\Str;
class StringMacro{
public function checkLength(string $str, int $length):bool
{
return function (string $str, int $length) {
return Static::length($str) === $length;
};
}
public function countVowel(string $str):int
{
return function (string $str) {
$vowels = 0;
$length = strlen($str);
for($i=0; $i =$length; $i++ ){
if(strstr('aeiouAEIOU', $str[$i])) $vowels++;
}
return $vowels;
};
}
}
Now we add App\Macro\StringMacro.php
class object into Str
Class through mixin() method that available in Macroable
trait.
<?php
namespace App\Providers;
use Illuminate\Http\Request;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;
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 App\Macro\StringMacro); // method like checkLength() or countVowel() method now available with Str
}
}
Lets have a look that how you can use these method.
<?php
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
\Illuminate\Support\Str::checkLength("This is Test", 12); // return true or false
\Illuminate\Support\Str::countVowel("This is Test"); // return total vowels
});
Its not limited we can use Macroable to our custom Classes. Lets have a Look.
App\Service\CustomService.php
<?php
namespace App\Service;
use Illuminate\Support\Traits\Macroable;
class CustomService
{
use Macroable;
}
Just One trait we can easily extends CustomService Class Functionality .
<?php
namespace App\Providers;
use App\Macro\RequestMacro;
use App\Service\CustomService;
use Illuminate\Http\Request;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
CustomService::macro("getBaseURL", function () {
return "https://dumpcoder.com";
});
}
}
Now Take a look how we use This method with our CustomService Class.
<?php
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
$service = new \App\Service\CustomService();
echo $service ->getBaseURL();
}
Conclusion
Small Thing but powerful feature of Laravel is Macro. We checked simple to advance example that we can use any of our projects. Its have one drawback that if someone new with Laravel he/she will confuse where are extra methods are coming from. But Its has one more benefits that we don’t need to create extra classes for a single method.
Hope you enjoy this article comment to show your love ❤️❤️❤️❤️❤️