Laravel 10 Macros Extending Laravel’s Core Classes

Hello Artisan, today I'll show you how to How to Using Extending Laravel’s Core Classes. Laravel Macros are like superpowers for expanding what Laravel can do. While you can already stretch Laravel's own classes, macros let you give new abilities to classes that you didn't create yourself. In this article, we'll explore how to make the most of Laravel Macros and identify the classes that are suitable for creating macros.

Table of Contents

  1. What is Laravel Macro?
  2. Macroable Laravel’s Classes
  3. Creating a Laravel Macro
  4. Creating Multiple Macros
  5. Conclusion

What is Laravel Macro?

Simply put, a Laravel Macro is like giving extra abilities to a part of Laravel that didn't have them before. It's as if you're adding new tricks to a tool in Laravel by writing some special code. To do this, Laravel offers a handy tool called the "Macroable" trait. An example of this is seen in the Response class of Laravel, found in Illuminate\Http\Response. This class uses the Macroable trait, allowing you to expand the Response class using a Macro.

Macroable Laravel’s Classes

The given Laravel classes use a trait called Illuminate\Support\Traits\Macroable to help you easily create your own macros. These classes, which are quite commonly used, provide a way to create macros effectively.

  • 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

There are other classes and facades which use the Macroable trait. You can find all the classes and facades in the codebase of Laravel.

Creating a Laravel Macro

Before you make a Laravel Macro, ensure that the class you want to modify uses the Macroable trait. We're going to make a new ability for the Illuminate\Support\Str class. This ability, called isLength, will help check the length of a provided string. To do this, define the ability within the boot() method of your AppServiceProvider class.

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;
        });
    }
}

In the boot method of AppServiceProvider, we're creating an isLength custom function for the Str class. This function compares the length of two values: the first one with the second one. Keep in mind that this custom function can take multiple parameters as you choose. It's worth noting that we're using static::length inside the custom function. This means the function can still use all the methods of the original class.

Now you can use this macro anywhere in your application.

use Illuminate\Support\Str;
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.

Let’s add another macro to Str the class which will append the given character to a given string.

Str::macro('appendTo', function ($str, $char) {
    return $char.$str;
});

Now you can call the above macro like below:

use Illuminate\Support\Str;
dd(Str::appendTo('Shouts', '@')); // @Shouts

Creating Multiple Macros

As your application grows, managing macros within the AppServiceProvider can get messy. Starting from Laravel 5.5, you can use class-based macros to keep your code cleaner.

In the previous example, we'll maintain our two macros but store them in a new class. This new class, named StrMixin, will be located in the app/Mixins folder. This approach helps organize your code better.

Add the below code:

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;
        };
    }
}

In your AppServiceProvider, you can delete the macros you defined earlier. Instead, you can utilize the mixin() method to set up all your macros for a specific class. Your updated AppServiceProvider will resemble the following after making these changes.

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.

Conclusion

Now you understand how to expand Laravel's main classes using something called Laravel Macros. Just make sure to confirm if the specific class you're working with supports this approach before proceeding. If you have any queries about Macros, feel free to ask them in the provided comment section.

That's it for today. I hope it'll be helpful in upcoming project.