Decomposition: the application of PHP magic method in laravel

Time:2020-5-31

Decomposition: the application of PHP magic method in laravel

Original link: https://learnku.com/laravel/t…

For discussion, please go to the professional laravel Developer Forum: https://learnku.com/Laravel

Laravel takes PHP to a whole new level, providing you with a great development experience (DX) for your next project. Therefore, some people call it “magic“.

Today, I’m going to show you one of laravel’s tricks,Magic Methods

What is magic?

It is important to understand that magic methods are not unique to laravel, but can be used in any PHP application. Laravel happens to have some of the most interesting magic method use cases.

Magic method is a method that can be used in any class declared in PHP. It provides a method to implement additional functions in a class.

Here’s a good definition:

Magic methods are never called by programmers – in fact, PHP will call them in the background. That’s why they’re called “magic” methods – because they’re never called directly, they allow programmers to do something very powerful.

There are 15 magic methods:

class MyClass
{
    public function __construct() {}

    public function __destruct() {}

    public function __call() {}

    public function __callStatic() {}

    public function __get() {}

    public function __set() {}

    public function __isset() {}

    public function __unset() {}

    public function __sleep() {}

    public function __wakeup() {}

    public function __toString() {}

    public function __invoke() {}

    public function __set_state() {}

    public function __clone() {}

    public function __debuginfo() {}
}

If you have done some object-oriented programming in PHP, you must know__constructMethod, this is a magic method. So you’ve been using magic.

You’ve also noticed that all magic methods are based on “UU” Prefixed.

Today, we won’t delve into these methods, but only into the interesting methods used throughout the Laraway code base. If others are interested, please feel free to check the following documents

PHP: Méthodes magiques – Manual

How laravel uses magic methods

__get()

The model in laravel is very special. Instead of storing attribute data as a direct attribute of a class, they store it in theprotected $attributesProperty, which is the related array of all data saved by the model.

Let’s look at the difference between a simple PHP class and a laravel model for accessing properties.

<?php

/**
 *The normal user class (not laravel) in PHP will only be a class with the above properties
 */
class NormalUser
{
    public $firstName = 'Alice';
}

$normalUser = new NormalUser;

$normaluser - > firstname; // will return 'Alice'
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

/**
 *A user class in laravel
 */
class LaravelUser extends Model
{
    /**
     *Note that we store all the attribute data in a separate array
     */
    protected $attributes = [
        'firstName' => 'Alice',
    ];
}

$laravelUser = new LaravelUser;

$laraveluser - > firstname; // still return 'Alice'

As we can see, the PHP and laravel classes above behave exactly the same.

In laravel’s case, however, properties are not stored as they are in normal PHP, but instead are concentrated in a single file called$attributesProperties of. We still try to access the right data, but how?

It’s all possible because_getMagic method. Let’s try to implement a simple example ourselves.

<?php

class NormalUser
{
    /**
     *Declare properties as in laravel
     */
    protected $attributes = [
        'firstName' => 'Alice',
    ];

    /**
     *  __ The get function takes a parameter
     *It will be the property name you want to access
     *In this case, $key = "firstname"
     */
    public function __get(string $key)
    {
        return $this->attributes[$key];
    }
}

$normalUser = new NormalUser;

$normaluser - > firstname; // will return 'Alice'

We did it!

We need to note that the magic method is only called if a property with a matching name cannot be found in the class_get。 This is a fallback method that is called when PHP cannot find the accessed property in the class. Therefore, in the following example, the magic method is not called at all_get

<?php

class NormalUser
{
    public $firstName = 'Bob';

    protected $attributes = [
        'firstName' => 'Alice',
    ];

    public function __get($key)
    {
        return $this->attributes[$key];
    }
}

$normalUser = new NormalUser;

/**
 *Since this attribute exists in the class, Bob will be returned
 *So there is no magic method called in this example__ Get
 */
$normalUser->firstName;

More is happening behind the scenes. If you want to learn more about how laravel’s model works exactly__getYou can see the source code below.

laravel/framework

__set()

Use magic methods when the property you are trying to set is not declared in the class_set。 Let’s look again at the difference between the normal PHP class and the model model in laravel.

<?php

class NormalUser
{
    public $firstName = 'Alice';
}

$normalUser = new NormalUser;

$normalUser->firstName = 'Bob';

$normalUser->firstName; // Will return 'Bob'
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class LaravelUser extends Model
{
    protected $attributes = [
        'firstName' => 'Alice',
    ];
}

$laravelUser = new LaravelUser;

$laravelUser->firstName = 'Bob';

$laravelUser->firstName; // Will return 'Bob' as well

As we can see, in this example, we are still trying to influenceBobValue that does not actually exist in the class but is in the property$ attributesMedium. Let’s try magic__ set

<?php

class NormalUser
{
    public $attributes = [
        'firstName' => 'Alice',
    ];

    /**
     * The magic method __set receives the $name you want to affect the value on
     * and the value
     */
    public function __set($key, $value)
    {
        $this->attributes[$key] = $value;
    }
}

$normalUser = new NormalUser;

$normalUser->firstName = 'Bob';

/**
 * As we don't have the __get magic method define in this example for simplicity sake,
 * we will access the $attributes directly
 */
$normalUser->attributes['firstName']; // Will return 'Bob'

Now let’s start! We successfully implemented it in laravel__ getand__ setBasic usage of magic method! They can do it in just a few lines of code!

Keep in mind that these magic methods are as simple as possible without involving too many details, because there are more than just use cases besides those. If you are curious about how it works, I invite you to do some exploration in person! (if you have any questions, please feel free to contact me on twitter)

Again, if you want to dig further, please link to the source code here

laravel/framework

Let’s move on to the last and most interesting thing!

__call() & __callStatic()

When the called method cannot be found in the class,__call()Will be called. In laravel, this magic method makes macros possible in PHP.

I won’t go into all the details of macros, but if you’re interested, here’s a good article that explains how to use them in a Laraway application

The Magic of Laravel Macros

Let’s try to see how to write a simple macro example.

<?php

class NormalUser
{
    public $firstName = 'Alice';

    public $lastName = 'Bob';
}

$normalUser = new NormalUser;

$normaluser - > fullname(); // since the "fullname" method is not declared, an error will be thrown

use__call, can define an array containing closure functions, which can be added to the application programmatically when we develop.

<?php

class NormalUser
{
    public $firstName = 'Alice';

    public $lastName = 'Bob';

    /**
     *Initialize our macro to an empty array, and assign values later
     */
    public static $macros = [];

    /**
     *Define a way to add a new macro
     *The first parameter is the name of the macro we want to define
     *The second parameter is the closure function that will be executed when the macro is called
     */
    public static function addMacro($name, $macro) {
        static::$macros[$name] = $macro;
    }

    /**
     * "__ Call "receives two parameters,
     *$name is the name of the called function, such as "fullname"
     *$arguments is all the arguments passed to the function. Here we use an empty array because our function does not need to pass arguments
     */
    public function __call(string $name, array $arguments) {
        /**
         *Get macro by name
         */
        $macro = static::$macros[$name];
        /**
         *The macro is then executed with parameters
         *Note: before calling, we need to bind the closure to "$this" to make the macro method execute in the same context
         */
        return call_user_func_array($macro->bindTo($this, static::class), $arguments);
    }
}

$normalUser = new NormalUser;

$normaluser - > fullname(); // this will break because we have neither defined the "fullname" macro nor the "fullname" method.

/**
 *Add "fullname" macro method
 */
NormalUser::addMacro('fullName', function () {
    return $this->firstName.' '.$this->lastName;
});

$normaluser - > fullname(); // now, return "Alice Bob"

Macros are more complex than that, but we try to use__callMagic method to create a simple working version of the macro.

Except for static methods,__callStaticand__callIt’s exactly the same.

If you’re going to do further research on your own, here’s the macro feature source code.

laravel/framework

summary

So, coders, when you first use laravel, you will feel that it is right. But by looking at the source code, you will understand how magic works behind the scenes.

Just like magic in real life, unreasonable things will not happen, especially in the code. There is always a line of code behind the program, just need you to find it.

Original link: https://learnku.com/laravel/t…

For discussion, please go to the professional laravel Developer Forum: https://learnku.com/Laravel

Recommended Today

The way of nonlinear optimization

Mathematical knowledge 1、 Nonlinear functionLinear function is another name of a function of first degree, then nonlinear function means that the function image is not a function of a straight line.Nonlinear functions include exponential function, power function, logarithmic function, polynomial function and so on. 2、 Taylor expansion1. Taylor formula:Taylor’s formula is to add a_ The […]