Heim  >  Artikel  >  PHP-Framework  >  Was ist eine magische Methode? So verwenden Sie es in Laravel

Was ist eine magische Methode? So verwenden Sie es in Laravel

青灯夜游
青灯夜游nach vorne
2022-09-26 20:21:271794Durchsuche

Was ist die magische Methode? Wie verwende ich es in Laravel? Der folgende Artikel stellt Ihnen vor, wie Sie PHP-Zaubermethoden in Laravel anwenden. Ich hoffe, er wird Ihnen hilfreich sein!

Was ist eine magische Methode? So verwenden Sie es in Laravel

Laravel bringt PHP auf ein ganz neues Niveau und bietet Ihnen ein großartiges Entwicklungserlebnis (DX) für Ihr nächstes Projekt. Deshalb nennen es manche Leute „Magie“.

Heute zeige ich dir einen Trick in Laravel, die Magische Methode.

Was ist eine magische Methode?

Es ist wichtig zu verstehen, dass magische Methoden nicht nur für Laravel gelten, sondern in jeder PHP-Anwendung verwendet werden können. Laravel verfügt zufällig über einige der interessantesten Anwendungsfälle für magische Methoden.

Magische Methoden sind Methoden, die in jeder in PHP deklarierten Klasse verfügbar sind und Methoden zum Implementieren zusätzlicher Funktionen in der Klasse bereitstellen.

Hier ist eine gute Definition:

Magische Methoden werden niemals vom Programmierer aufgerufen – tatsächlich ruft PHP die Methode im Hintergrund auf. Aus diesem Grund werden sie „magische“ Methoden genannt – da sie nie direkt aufgerufen werden, ermöglichen sie dem Programmierer, einige sehr mächtige Dinge zu tun.

Es gibt insgesamt 15 magische Methoden:

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() {}
}

Wenn Sie objektorientierte Programmierung in PHP durchgeführt haben, müssen Sie die Methode __construct kennen, bei der es sich um eine magische Methode handelt. Sie haben also magische Methoden angewendet. __construct 方法,这是一个魔术方法。所以您一直在使用魔术方法。

您还注意到,所有的魔术的方法都是以“__”为前缀的。

今天,我们不会深入研究这些方法,而只会深入了解整个Laravel代码库中使用的那些有趣的方法。如果其他人对此感兴趣,请随时查看下面的文档?

PHP: Méthodes magiques - Manual

Laravel是如何使用的魔术方法

<span style="font-size: 16px;">__get()</span>

Laravel中的模型非常特别。它们不将属性数据存储为类的直接属性,而是存储在protected $attributes 属性中,该属性是模型所保存的所有数据的相关数组。

让我们看看简单的PHP类和Laravel模型访问属性的区别。

<?php

/**
 * PHP中的普通用户类(非Laravel)将只是一个具有上述属性的类
 */
class NormalUser
{
    public $firstName = &#39;Alice&#39;;
}

$normalUser = new NormalUser;

$normalUser->firstName; // 将返回'Alice'
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

/**
 * Laravel中的一个user类
 */
class LaravelUser extends Model
{
    /**
     * 注意,我们将所有属性数据存储在一个单独的数组中
     */
    protected $attributes = [
        &#39;firstName&#39; => 'Alice',
    ];
}

$laravelUser = new LaravelUser;

$laravelUser->firstName; // 依然返回'Alice'

我们可以看到,上面的PHP和Laravel类的行为完全相同。

然而,在Laravel的例子中,属性不像普通PHP那样存储,而是集中在一个名为$attributes的属性中。我们仍然设法访问正确的数据,但是如何访问呢?

这一切都是可能的,这是因为_get魔术方法。让我们自己尝试实现一个简单的例子。

<?php

class NormalUser
{
    /**
     * 像在Laravel中那样声明属性
     */
    protected $attributes = [
        &#39;firstName&#39; => 'Alice',
    ];

    /**
     *  __get 函数接收一个参数
     * 它将会是你想要访问的属性名
     * 在这个例子中是 $key = "firstName"
     */
    public function __get(string $key)
    {
        return $this->attributes[$key];
    }
}

$normalUser = new NormalUser;

$normalUser->firstName; // 将会返回 'Alice'

我们做到了! ?

我们需要注意,只有在类中找不到具有匹配名称的属性时,才会调用魔术方法_get。这是一种后备方法,当PHP在类中找不到所访问的属性时调用。因此,在下面的示例中,根本不会调用魔术方法_get

<?php

class NormalUser
{
    public $firstName = &#39;Bob&#39;;

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

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

$normalUser = new NormalUser;

/**
 * 由于类中存在该属性,将会返回 Bob
 * 所以该例子中没有调用到魔术方法__get
 */
$normalUser->firstName;

有更多的事情在幕后发生。如果你想更多地了解 Laravel 的模型是如何确切地使用 __get 的,你可以查看下面的源代码。

laravel/framework

<span style="font-size: 16px;">__set()</span>

当试图设置的属性没有在类中声明时,使用魔术方法_set。让我们再次看看normal PHP类和Laravel中model模型的区别。

<?php

class NormalUser
{
    public $firstName = &#39;Alice&#39;;
}

$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 = [
        &#39;firstName&#39; => 'Alice',
    ];
}

$laravelUser = new LaravelUser;

$laravelUser->firstName = 'Bob';

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

如我们所见,在此示例中,我们仍然尝试影响Bob的值,该值在类中实际上不存在但位于属性$ attributes中。让我们尝试使用魔术方法__ set

<?php

class NormalUser
{
    public $attributes = [
        &#39;firstName&#39; => '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'

现在我们开始!我们在Laravel中成功实施了__ get__ set

Sie haben auch bemerkt, dass allen magischen Methoden das Präfix „__“ vorangestellt ist.

Heute werden wir uns nicht mit diesen Methoden befassen, sondern nur mit den interessanten, die in der gesamten Laravel-Codebasis verwendet werden. Wenn noch jemand Interesse hat, schauen Sie sich gerne die Dokumentation unten an?

PHP: Magische Methoden – Handbuch

So verwenden Sie magische Methoden in Laravel🎜🎜🎜🎜🎜🎜<span style="font-size: 16px;">__get()🎜</span>🎜 🎜🎜Models in Laravel sind etwas ganz Besonderes. Sie speichern Attributdaten nicht als direkte Attribute der Klasse, sondern im Attribut protected $attributes, einem assoziativen Array aller vom Modell enthaltenen Daten. 🎜🎜Sehen wir uns den Unterschied zwischen einfachen PHP-Klassen- und Laravel-Modellzugriffseigenschaften an. 🎜
<?php

class NormalUser
{
    public $firstName = &#39;Alice&#39;;

    public $lastName = &#39;Bob&#39;;
}

$normalUser = new NormalUser;

$normalUser->fullName(); // 由于没有声明 "fullName" 方法,这将会抛出错误
<?php

class NormalUser
{
    public $firstName = &#39;Alice&#39;;

    public $lastName = &#39;Bob&#39;;

    /**
     * 将我们的宏初始化为一个空数组,后面再赋值
     */
    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”
🎜Wir können sehen, dass sich die oben genannten PHP- und Laravel-Klassen genau gleich verhalten. 🎜🎜Allerdings werden im Fall von Laravel die Attribute nicht wie normales PHP gespeichert, sondern in einem Attribut namens $attributes konzentriert. Wir schaffen es immer noch, auf die richtigen Daten zuzugreifen, aber wie? 🎜🎜Das alles ist dank der magischen Methode _get möglich. Versuchen wir, ein einfaches Beispiel selbst umzusetzen. 🎜rrreee🎜Wir haben es geschafft! ?🎜🎜Wir müssen beachten, dass die magische Methode _get nur aufgerufen wird, wenn in der Klasse keine Eigenschaft mit passendem Namen gefunden wird. Dies ist eine Fallback-Methode, die aufgerufen wird, wenn PHP die Eigenschaft, auf die in der Klasse zugegriffen wird, nicht finden kann. Daher wird im folgenden Beispiel die magische Methode _get überhaupt nicht aufgerufen. 🎜rrreee🎜 Hinter den Kulissen passiert noch mehr. Wenn Sie mehr darüber erfahren möchten, wie genau die Modelle von Laravel __get verwenden, können Sie sich den Quellcode unten ansehen. 🎜🎜laravel/framework🎜🎜🎜 🎜 🎜🎜<span style="font-size: 16px;">__set()🎜</span>🎜🎜🎜Verwenden Sie die magische Methode _set, wenn die Eigenschaft, die Sie festlegen möchten, nicht deklariert ist im Klassencode>. Schauen wir uns noch einmal den Unterschied zwischen normalen PHP-Klassen und Modellen in Laravel an. 🎜rrreeerrreee🎜Wie wir sehen können, versuchen wir in diesem Beispiel immer noch, den Wert von <code>Bob zu beeinflussen, der eigentlich nicht in der Klasse existiert, sondern im Attribut $ attributes steht . Versuchen wir es mit der magischen Methode __ set🎜rrreee🎜Jetzt legen wir los! Wir haben die grundlegende Verwendung der magischen Methoden __ get und __ set in Laravel erfolgreich implementiert! Sie können es mit nur wenigen Codezeilen tun! 🎜🎜Bitte denken Sie daran, dass diese magischen Methoden so einfach wie möglich sind, ohne zu sehr ins Detail zu gehen, denn es gibt mehr als nur diese und nicht nur Anwendungsfälle, und wenn Sie neugierig sind, wie es funktioniert, lade ich Sie ein, etwas zu erkunden für dich selbst! (Kontaktieren Sie mich auch gerne auf Twitter, wenn Sie Fragen haben) 🎜🎜Wenn Sie noch einmal tiefer in die Materie eintauchen möchten, finden Sie hier den Link zum Quellcode 🎜🎜🎜laravel/framework🎜🎜🎜Lassen Sie uns mit dem letzten fortfahren Auch das Interessanteste! ?🎜

<span style="font-size: 16px;">__call()</span> & <span style="font-size: 16px;">__callStatic()</span>

当调用的方法在类中找不到时,__call()会被调用。 在laravel中,该魔术方法方法使宏在 php 中成为可能。

我不会深入讨论宏的所有细节,但如果您感兴趣,这里有一篇很好的文章解释了如何在 Laravel 应用程序中使用它们?

The Magic of Laravel Macros

让我们试着看看如何编写一个简单的宏示例。

<?php

class NormalUser
{
    public $firstName = &#39;Alice&#39;;

    public $lastName = &#39;Bob&#39;;
}

$normalUser = new NormalUser;

$normalUser->fullName(); // 由于没有声明 "fullName" 方法,这将会抛出错误

使用 __call ,可以定义一个包含闭包函数的数组,在我们开发时可以程序化地添加到应用里。

<?php

class NormalUser
{
    public $firstName = &#39;Alice&#39;;

    public $lastName = &#39;Bob&#39;;

    /**
     * 将我们的宏初始化为一个空数组,后面再赋值
     */
    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/framework

总结

所以说码农们,当你第一次用 Laravel 会感觉它神奇是对的,但是通过深入查看源代码,你会理解魔法是如何在场景背后施展的。

就像现实生活中的魔法,没有道理的事情是不会发生的,在代码中就更加是了。程序运行的背后总是有着一行代码在执行,只不过需要你去发现它。

英文原文地址:https://dev.to/stvnyung/laravel-greatest-trick-revealed-magic-methods-31om

译文地址:https://learnku.com/laravel/t/40926

【相关推荐:laravel视频教程

Das obige ist der detaillierte Inhalt vonWas ist eine magische Methode? So verwenden Sie es in Laravel. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:learnku.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen