Maison  >  Article  >  cadre php  >  Qu'est-ce qu'une méthode magique ? Comment l'utiliser dans Laravel

Qu'est-ce qu'une méthode magique ? Comment l'utiliser dans Laravel

青灯夜游
青灯夜游avant
2022-09-26 20:21:271884parcourir

Quelle est la méthode magique ? Comment l’utiliser dans Laravel ? L'article suivant vous présentera comment appliquer les méthodes magiques PHP dans Laravel. J'espère qu'il vous sera utile !

Qu'est-ce qu'une méthode magique ? Comment l'utiliser dans Laravel

Laravel amène PHP à un tout nouveau niveau, vous offrant une excellente expérience de développement (DX) pour votre prochain projet. C’est pourquoi certains l’appellent « magique ».

Aujourd'hui, je vais vous montrer une astuce dans Laravel, la Méthode Magique.

Quelle est la méthode magique ?

Il est important de comprendre que les méthodes magiques ne sont pas propres à Laravel mais peuvent être utilisées dans n'importe quelle application PHP. Laravel possède certains des cas d'utilisation les plus intéressants pour les méthodes magiques.

Les méthodes magiques sont des méthodes disponibles dans n'importe quelle classe déclarée en PHP qui fournissent des méthodes pour implémenter des fonctionnalités supplémentaires dans la classe.

Voici une bonne définition :

Les méthodes magiques ne sont jamais appelées par le programmeur - en fait, PHP appellera la méthode en coulisse. C'est pourquoi on les appelle méthodes « magiques » : parce qu'elles ne sont jamais appelées directement, elles permettent au programmeur de faire des choses très puissantes.

Il existe 15 méthodes magiques au 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() {}
}

Si vous avez fait de la programmation orientée objet avec PHP, alors vous devez connaître la méthode __construct, qui est une méthode magique. Vous avez donc utilisé des méthodes magiques. __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

Vous avez également remarqué que toutes les méthodes magiques sont préfixées par "__".

Aujourd'hui, nous n'aborderons pas ces méthodes, mais uniquement celles intéressantes utilisées dans toute la base de code Laravel. Si quelqu'un d'autre est intéressé, n'hésitez pas à consulter la documentation ci-dessous ?

PHP : Méthodes magiques - Manuel

Comment utiliser les méthodes magiques dans Laravel🎜🎜🎜🎜🎜🎜<span style="font-size: 16px;">__get()🎜</span>🎜 🎜🎜Les modèles à Laravel sont très spéciaux. Ils ne stockent pas les données d'attribut en tant qu'attributs directs de la classe, mais dans l'attribut protected $attributes, qui est un tableau associatif de toutes les données détenues par le modèle. 🎜🎜Voyons la différence entre une simple classe PHP et les propriétés d'accès au modèle Laravel. 🎜
<?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”
🎜Nous pouvons voir que les classes PHP et Laravel ci-dessus se comportent exactement de la même manière. 🎜🎜Cependant, dans le cas de Laravel, les attributs ne sont pas stockés comme PHP normal, mais sont plutôt concentrés dans un attribut appelé $attributes. Nous parvenons toujours à accéder aux bonnes données, mais comment ? 🎜🎜Tout cela est possible grâce à la méthode magique _get. Essayons de mettre en œuvre nous-mêmes un exemple simple. 🎜rrreee🎜Nous l'avons fait ! ?🎜🎜Nous devons noter que la méthode magique _get ne sera appelée que si une propriété avec un nom correspondant n'est pas trouvée dans la classe. Il s'agit d'une méthode de secours appelée lorsque PHP ne trouve pas la propriété à laquelle on accède dans la classe. Par conséquent, dans l'exemple suivant, la méthode magique _get n'est pas du tout appelée. 🎜rrreee🎜 Il se passe bien plus dans les coulisses. Si vous souhaitez en savoir plus sur la manière exacte dont les modèles de Laravel utilisent __get, vous pouvez consulter le code source ci-dessous. Laravel/framework🎜🎜 🎜 🎜🎜<span style="font-size: 16px;">__set()🎜</span>🎜🎜🎜Utilisez la méthode magique _set lorsque la propriété que vous essayez de définir n'est pas déclarée dans le code de la classe>. Examinons à nouveau la différence entre les classes PHP normales et les modèles dans Laravel. 🎜rrreeerrreee🎜Comme nous pouvons le voir, dans cet exemple nous essayons toujours d'affecter la valeur de <code>Bob qui n'existe pas réellement dans la classe mais est dans l'attribut $ attributs . Essayons d'utiliser la méthode magique __ set🎜rrreee🎜Maintenant, commençons ! Nous avons implémenté avec succès l'utilisation de base des méthodes magiques __ get et __ set dans Laravel ! Ils peuvent le faire avec seulement quelques lignes de code ! 🎜🎜N'oubliez pas que ces méthodes magiques sont aussi simples que possible sans entrer dans trop de détails, car il y a bien plus que celles-là et pas seulement des cas d'utilisation, et si vous êtes curieux de savoir comment cela fonctionne, je vous invite à faire un peu d'exploration pour vous-même ! (Vous pouvez aussi toujours me contacter sur Twitter si vous avez des questions) 🎜🎜Encore une fois, si vous souhaitez approfondir, voici le lien vers le code source 🎜🎜🎜laravel/framework🎜🎜🎜Passons au dernier aussi La chose la plus intéressante ! ?🎜

<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视频教程

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer