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 Macro
s 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;
});
Post comment 取消回复