Use of macroable macros in Laravel

Source: Internet
Author: User
Tags traits
This article mainly introduces the use of macroable macros in Laravel, has a certain reference value, now share to everyone, the need for friends can refer to

the definition of Baidu Encyclopedia:
Macro in computer science is a kind of title for batch processing. Generally, a macro is a rule or pattern, or syntax substitution, that describes how a particular input (usually a string) is converted to the corresponding output (usually a string) based on a predefined rule. This substitution occurs during precompilation, called macro expansion.
    • The first time I came in touch with a macro was when my teacher spoke office when I was in college on computer fundamentals. When the teacher introduced the macro operation did not care too much, only remember that this operation is very powerful, it can make the daily work easier.

    • Today we are talking about macro operations in Laravel

The first complete source code

<?phpnamespace illuminate\support\traits;use closure;use reflectionclass;use ReflectionMethod;use     Badmethodcallexception;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 FUNCTI    On macro ($name, $macro) {static:: $macros [$name] = $macro;     }/** * Mix another object into the class. * * @param object $mixin * @return void */public static function Mixin ($mixin) {$methods = (n EW Reflectionclass ($mixin))->getmethods (Reflectionmethod::is_public |        reflectionmethod::is_protected);            foreach ($methods as $method) {$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 is    Set (static:: $macros [$name]);     }/** * Dynamically handle calls to the class. * * @param string $method * @param array $parameters * @return Mixed * * @throws \badmethodcallex             Ception */public static function __callstatic ($method, $parameters) {if (! Static::hasmacro ($method)) {        throw new Badmethodcallexception ("Method {$method} does not exist."); } if (static:: $macros [$method] instanceof Closure) {return Call_user_func_array (Closure::bind (static::$        macros[$method], NULL, static::class), $parameters);    } return Call_user_func_array (static:: $macros [$method], $parameters);     }/** * Dynamically handle calls to the class. * * @param string $method * @param array $parameters * @return Mixed * * @throws \badmethodcallex Ception */Public Function __call ($method, $parameters) {if (! Static::hasmacro ($method)) {throw new Badm        Ethodcallexception ("Method {$method} does not exist.");        } $macro = static:: $macros [$method]; if ($macro instanceof Closure) {return Call_user_func_array ($macro->bindto ($this, Static::class), $paramete        RS);    } return Call_user_func_array ($macro, $parameters); }}
    • Macroable::macroMethod

public static function Macro ($name, $macro) {    static:: $macros [$name] = $macro;}

Very simple code, according to the parameters of the comments, $macro can be passed a closure or object, the reason can be transmitted to the object, thanks to the Magic method in PHP

Class father{    //By adding the Magic method **__invoke** we can use the object as a closure. Public    function __invoke ()    {        echo __class__;    }} Class child{use    \illuminate\support\traits\macroable;} With the addition of macros, we can invoke methods that do not exist in the child object Child::macro (' Show ', new Father);//output: Father (New Child)->show ();
    • Macroable::mixinMethod

This method injects the return result of an object's method into the original object

public static function Mixin ($mixin) {//gets all the exposed and protected methods in the object by reflection $methods = (new Reflectionclass ($mixin))->getmethods (Reflectionmethod::is_public |    reflectionmethod::is_protected);                The foreach ($methods as $method) {//setting method is accessible because the protected cannot be called externally $method->setaccessible (true);    Call the macro method to bulk Create macros Static::macro ($method->name, $method->invoke ($mixin));        }}//actually uses the class father{public function say () {return function () {echo ' say ';    };        Public function Show () {return function () {echo ' show ';    };        } protected function Eat () {return function () {echo ' eat ';    }; }}class child{use \illuminate\support\traits\macroable;} Bulk bound macro directive child::mixin (new Father); $child = new child;//output: Say$child->say ();//output: Show$child->show ();//output: eat$ Child->eat (); 

As you can see in the code above, mixin you can bind a method of a class to a macro class. It is important to note that the method must return a closure type.

    • Macroable::hasMacroMethod

public static function Hasmacro ($name) {    return isset (static:: $macros [$name]);}

This method is relatively simple and there is nothing complicated to judge whether there is a macro directive. This is usually preceded by the use of macro directives.

    • Macroable::__calland Macroable::__callStatic methods

Just because of these two methods, we can do macro operation, two methods in addition to the implementation of different ways, the code is similar. Here, let's talk.__call

Public Function __call ($method, $parameters) {    //If this macro is not present, throw the exception directly if    (! Static::hasmacro ($method)) {        throw new Badmethodcallexception ("Method {$method} does not exist.");    The macro command that gets stored    $macro = static:: $macros [$method];    Closures do a little bit of special handling    if ($macro instanceof Closure) {        return Call_user_func_array ($macro->bindto ($this, Static:: Class), $parameters);    }    Not closures, such as objects, run directly through this method, but make sure that the object has a ' __invoke ' method    return Call_user_func_array ($macro, $parameters);} Class child{use    \illuminate\support\traits\macroable;    protected $name = ' father ';} The special handling of closures, the need to do is to bind $this, such as Child::macro (' Show ', function () {    echo $this->name;}); /output: Father (new Child)->show ();

In the above operation, when we bind a macro, we can $this invoke the property in the closure Child , because __call we use the method in the method Closure::bindTo .

explanation of the official website Closure::bindTo : Copy the current closure object, binding the specified $this object and the class scope.

Adding macro directives to classes in Laravel

There are many classes in Laravel that use macros.trait



For example Illuminate\Filesystem\Filesystem::class , we want to add a method to this class, but we don't move the code inside.

    1. We only need to App\Providers\AppServiceProvider::register add macro instructions to the method (you can also create a new service provider specifically to handle)


1. Then add a test route to test our new added method


2. Then open the browser to run, you will find that our code can run properly and output the results

The above is the whole content of this article, I hope that everyone's learning has helped, more relevant content please pay attention to topic.alibabacloud.com!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.