Home > Article > PHP Framework > What is a magic method? How to use it in Laravel
What is a magic method? How to use it in Laravel? The following article will introduce to you how to apply PHP magic methods in Laravel. I hope it will be helpful to you!
#Laravel takes PHP to a whole new level, providing a great development experience (DX) for your next project. Therefore, some people call it "magic".
Today, I will show you a trick in Laravel, Magic Method.
It is important to understand that magic methods are not unique to Laravel and can be used in any PHP application. Laravel happens to have some of the most interesting use cases for magic methods.
Magic methods are methods available in any class declared in PHP that provide ways to implement additional functionality in the class.
Here's a good definition:
The magic method will never be called by the programmer - in fact, PHP will call the method behind the scenes. This is why they are called "magic" methods - because they are never called directly, they allow the programmer to do some very powerful things.
There are 15 magic methods in total:
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 with PHP, then you must know the __construct
method, which is A magic method. So you've been using magic methods.
You also noticed that all magic methods are prefixed with "__".
Today we won’t delve into these methods, but only the interesting ones used throughout the Laravel codebase. If anyone else is interested, feel free to check out the documentation below?
PHP: Méthodes magiques - Manual
<span style="font-size: 16px;">__get()</span>
in Laravel The model is very special. They do not store attribute data as direct attributes of the class, but in the protected $attributes
attribute, which is an associative array of all the data held by the model.
Let’s look at the difference between simple PHP classes and Laravel model access properties.
<?php /** * PHP中的普通用户类(非Laravel)将只是一个具有上述属性的类 */ class NormalUser { public $firstName = 'Alice'; } $normalUser = new NormalUser; $normalUser->firstName; // 将返回'Alice'
<?php namespace App; use Illuminate\Database\Eloquent\Model; /** * Laravel中的一个user类 */ class LaravelUser extends Model { /** * 注意,我们将所有属性数据存储在一个单独的数组中 */ protected $attributes = [ 'firstName' => 'Alice', ]; } $laravelUser = new LaravelUser; $laravelUser->firstName; // 依然返回'Alice'
We can see that the above PHP and Laravel classes behave exactly the same.
However, in Laravel's case, the attributes are not stored like normal PHP, but are instead concentrated in a single attribute called $attributes
. We still manage to access the correct data, but how?
This is all possible because of the _get
magic method. Let's try to implement a simple example ourselves.
<?php class NormalUser { /** * 像在Laravel中那样声明属性 */ protected $attributes = [ 'firstName' => 'Alice', ]; /** * __get 函数接收一个参数 * 它将会是你想要访问的属性名 * 在这个例子中是 $key = "firstName" */ public function __get(string $key) { return $this->attributes[$key]; } } $normalUser = new NormalUser; $normalUser->firstName; // 将会返回 'Alice'
We did it! ?
We need to note that the magic method _get
will only be called if a property with a matching name is not found in the class. This is a fallback method called when PHP cannot find the property being accessed in the class. Therefore, in the example below, the magic method _get
is not called at all.
<?php class NormalUser { public $firstName = 'Bob'; protected $attributes = [ 'firstName' => 'Alice', ]; public function __get($key) { return $this->attributes[$key]; } } $normalUser = new NormalUser; /** * 由于类中存在该属性,将会返回 Bob * 所以该例子中没有调用到魔术方法__get */ $normalUser->firstName;
There's more going on behind the scenes. If you want to know more about how exactly Laravel's models use __get
, you can check out the source code below.
##__set()<span style="font-size: 16px;"></span>
_set when the property you are trying to set is not declared in the class. Let's look again at the difference between normal PHP classes and models 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 wellAs we can see, in this example we are still trying to affect the value of
Bob which does not actually exist in the class but is in the attribute
$ attributesmiddle. Let's try the magic method
__ 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 we get started! We have successfully implemented the basic usage of the
__ get and
__ set magic methods in Laravel! They can do it with just a few lines of code!
<span style="font-size: 16px;">__call()</span>
& <span style="font-size: 16px;">__callStatic()</span>
当调用的方法在类中找不到时,__call()
会被调用。 在laravel中,该魔术方法方法使宏在 php 中成为可能。
我不会深入讨论宏的所有细节,但如果您感兴趣,这里有一篇很好的文章解释了如何在 Laravel 应用程序中使用它们?
让我们试着看看如何编写一个简单的宏示例。
<?php class NormalUser { public $firstName = 'Alice'; public $lastName = 'Bob'; } $normalUser = new NormalUser; $normalUser->fullName(); // 由于没有声明 "fullName" 方法,这将会抛出错误
使用 __call
,可以定义一个包含闭包函数的数组,在我们开发时可以程序化地添加到应用里。
<?php class NormalUser { public $firstName = 'Alice'; public $lastName = 'Bob'; /** * 将我们的宏初始化为一个空数组,后面再赋值 */ public static $macros = []; /** * 定义一个添加新宏的方法 * 第一个参数是我们想要定义的宏的名字 * 第二个参数是调用宏时将会被执行的闭包函数 */ public static function addMacro($name, $macro) { static::$macros[$name] = $macro; } /** * "__call" 接收两个参数, * $name 是被调用的函数名称,比如 “fullName” * $arguments 是传递给函数的所有参数,这里我们使用了一个空数组,因为我们的函数不用传参 */ public function __call(string $name, array $arguments) { /** * 通过名称获取到宏 */ $macro = static::$macros[$name]; /** * 然后通过参数执行宏 * 备注:调用之前,我们需要将闭包绑定到 “$this”,从而使宏方法在同样的上下文中执行 */ return call_user_func_array($macro->bindTo($this, static::class), $arguments); } } $normalUser = new NormalUser; $normalUser->fullName(); // 这里会中断,因为我们既没有定义 “fullName” 宏,也没有 “fullName” 方法存在。 /** * 添加 “fullName” 宏方法 */ NormalUser::addMacro('fullName', function () { return $this->firstName.' '.$this->lastName; }); $normalUser->fullName(); // 现在,返回 “Alice Bob”
宏要比那个复杂一些,但是我们设法使用 __call
魔术方法来创建一个宏的简单工作版本。
除了对于静态方法, __callStatic
和 __call
是完全一样的。
如果你打算自己再深入研究,这里有宏的特性源代码。
所以说码农们,当你第一次用 Laravel 会感觉它神奇是对的,但是通过深入查看源代码,你会理解魔法是如何在场景背后施展的。
就像现实生活中的魔法,没有道理的事情是不会发生的,在代码中就更加是了。程序运行的背后总是有着一行代码在执行,只不过需要你去发现它。
英文原文地址:https://dev.to/stvnyung/laravel-greatest-trick-revealed-magic-methods-31om
译文地址:https://learnku.com/laravel/t/40926
【相关推荐:laravel视频教程】
The above is the detailed content of What is a magic method? How to use it in Laravel. For more information, please follow other related articles on the PHP Chinese website!