You can understand it as a method in trait, which is similar to the method in helpers in the commonly used helper files in our development. Its purpose is to horizontally expand Laravel's internal components for global use.

Let's look at an example:

One of the fields in the User table is is_vip, which is used to record whether the user is a VIP. When we judge in the controller, the normal writing is:

// UserController.php

public function getVip(Request $request)
{
if($request->user()->is_vip)
{
return true;
}
return false;
}

When multiple controllers have branches that judge the is_vip field, the code becomes redundant. If is_vip is true, there are other judgments later, then the nested if statement will be Make the code logic more complex.

if($request->user()->is_vip)
{
if(...)
{
...
}
}

It would be nice if we could add a method to the Illuminate\Http\Request class to determine the value of the requesting user is_vip, Macro is used to do this, let's rewrite the previous method:

public function getVip(Request $request)
{
// Write it temporarily in the controller first.
Request::macro('isVip', function()
{
if(auth()->check()) // Make authorization judgment first to increase code robustness
{
return $this->user()->is_vip; // Equivalent to $request->user()->is_vip, $this points to the Request instance.
}
return false;
}

// This way the controller has only one line of code.
return $request->isVip();
}

$this in Macro refers to the instance of the extended method, and $this above refers to the Request instance injected in the controller.

As another example, it is often necessary to judge whether the length of the string is greater than or equal to the specified length in the project, usually like this:

use Illuminate\Support\Str;
public function str()
{
$length = 3;
$str1 = 'cbd';
if(Str::length($str1) >= $length)
{
return true;
}
return false;
}

Rewritten using Macro as follows:

use Illuminate\Support\Str;
public function str()
{
// Write it temporarily in the controller first.
    Str::macro('lengthCheck', function(string $str1, int $length)
    {
        if(self::length($str1) >= $length)
{
return true;
}
return false;
    });

// This way the controller has only one line of code.
return Str::lengthCheck($str1, $length);
}

Well, here we have a basic concept of Macro, have you used mouse macros? Isn't it just an extension of the mouse function? The mouse itself does not have the function of connecting points, but it provides an interface to allow us to customize the programming to achieve the functions we want.

Next, we also need to let Macro be loaded together when the framework is loaded, so as to implement a global call, you can write it in AppServiceProvider.php, if there are not many, it depends on the situation.

In this example we will create a Provider to put these Macros together uniformly.

php artisan make:provider MacrosServiceProvider

Put the above two Macro into MacrosServiceProvider

<?php

namespace App\Providers;

use Illuminate\Http\Request;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;

class MacrosServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
// Determine if the user is a VIP
        Request::macro('isVip', function(){
            if(auth()->check())
            {
                return $this->user()->is_vip;
            }
            return false;
        });

// Determine if the string is greater than or equal to the given length
        Str::macro('lengthCheck', function(string $str1, int $length)
        {
            if(static::length($str1) >= $length)
            {
                return true;
            }
            return false;
        });

    }
}

Load it in app.php

'providers' => [
...
\App\Providers\MacrosServiceProvider::class,
];

Consider using Macro more in development to make your code more readable and reusable, I hope this article is helpful to you.

Finally, which Laravel components can be extended with Macro:

  • 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

postscript:
The solution to the problem that PHPSTORM IDE does not have Macro prompts:

Install the barryvdh/laravel-ide-helper component

composer require --dev barryvdh/laravel-ide-helper

Just follow the document step by step. Note that there is a sentence in the document. If you want to use code hints, you must write it according to the requirements in the document:

Automatically generate PHPDoc for Macros and Mixins

This package can generate PHPDocs for Macros and Mixins, which will be added to the _ide_helper.php file.

But this only works if you use type hints when declaring the macro.

Str::macro('concat', function(string $str1, string $str2) : string {
    return $str1 . $str2;
});
点赞(0)

评论列表 共有 0 评论

暂无评论

微信服务号

微信客服

淘宝店铺

support@elephdev.com

发表
评论
Go
顶部