搜索
首页php框架Laravel什么是魔术方法?如何在 Laravel 中使用

什么是魔术方法?如何在 Laravel 中使用

Sep 26, 2022 pm 08:21 PM
phplaravel魔术方法

什么是魔术方法?如何在 Laravel 中的应用?下面本篇文章给大家介绍一下PHP 魔术方法在 Laravel中应用的方法,希望对大家有所帮助!

什么是魔术方法?如何在 Laravel 中使用

Laravel将PHP应用到了一个全新的水平,为您打造下一个项目提供了出色的开发体验(DX)。因此,一些人将其称为“魔术”。

今天,我将向您展示Laravel的一个技巧,魔术方法

什么是魔术方法?

重要的是,要了解魔术方法并不是Laravel独有的,而是可以在任何PHP应用中使用。Laravel恰好有一些最有趣的魔术方法用例。

魔术方法是在PHP中声明的任何类中都可以使用的方法,它提供了在类中实现附加功能的方法。

这里有一个很好的定义:

魔术方法永远不会被程序员调用——实际上,PHP将在后台调用该方法。这就是为什么它们被称为“魔术”方法——因为它们从来没有被直接调用,它们允许程序员做一些非常强大的是事情。

总共有15中魔术方法:

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

如果您用PHP做过一些面向对象的编程,那么您一定知道 __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魔术方法的基本用法!他们只需几行代码就能完成!

请记住,这些魔术方法尽可能简单,而不必涉及太多细节,因为除了那些还有更多而不仅仅是用例,如果您对它的工作原理感到好奇,我邀请您亲自做一些探索! (如果您有任何疑问,也可以随时在Twitter上与我联系)

同样,如果您想进一步挖掘,请在此处链接到源代码

laravel/framework

让我们继续最后一个也是最有趣的一个事! ?

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

以上是什么是魔术方法?如何在 Laravel 中使用的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:learnku。如有侵权,请联系admin@php.cn删除
Laravel的最新版本是什么?Laravel的最新版本是什么?Apr 24, 2025 pm 05:17 PM

Laravel10,releasedonFebruary7,2023,isthelatestversion.Itfeatures:1)Improvederrorhandlingwithanewreportmethodintheexceptionhandler,2)EnhancedsupportforPHP8.1featureslikeenums,and3)AnewLaravel\Promptspackageforinteractivecommand-lineprompts.

最新的Laravel版本如何简化开发?最新的Laravel版本如何简化开发?Apr 24, 2025 pm 05:01 PM

thelatestlaravelververversionenhancesdevelopmentwith:1)简化的inimpliticmodelbinding,2)增强EnhancedeloquentcapabibilitionswithNewqueryMethods和3)改善了supportorfortormodernphpfortornphpforternphpfeatureserslikenamedargenamedArgonedArgonsemandArgoctess,makecodingMoreftermeforefterMealiteFficeAndEnjoyaigaigaigaigaigaiganigaborabilyaboipaigyAndenjoyaigobyabory。

在哪里可以找到最新的Laravel版本的发行说明?在哪里可以找到最新的Laravel版本的发行说明?Apr 24, 2025 pm 04:53 PM

你可以在laravel.com/docs找到最新Laravel版本的发布说明。1)发布说明提供了新功能、错误修复和改进的详细信息。2)它们包含示例和解释,帮助理解新功能的应用。3)注意新功能的潜在复杂性和向后兼容性问题。4)定期审查发布说明可以保持更新并激发创新。

远程工具包:在分布式团队中保持连接的基本工具远程工具包:在分布式团队中保持连接的基本工具Apr 24, 2025 pm 04:37 PM

theessentialToolSforStayingConnectedIndistributedTeamSinclude:1)CommunicationToolSlikeZoom,Microsoftteams,Slack和DiscordForeFforeffectiveCommunication; 2)ProjectManagementtoolsSuchastrello,Asana,Asana和JirafortaskManagementAngeandWorkFloworGanization jiralagementtoolssuchastrello,Asana和Jiraforterforloganization;

Laravel的影响:简化网络开发Laravel的影响:简化网络开发Apr 21, 2025 am 12:18 AM

Laravel通过简化Web开发过程和提供强大功能脱颖而出。其优势包括:1)简洁的语法和强大的ORM系统,2)高效的路由和认证系统,3)丰富的第三方库支持,使得开发者能专注于编写优雅的代码并提高开发效率。

Laravel:前端还是后端?澄清框架的角色Laravel:前端还是后端?澄清框架的角色Apr 21, 2025 am 12:17 AM

laravelispredminandermanthandermanthandermanthandermanthermanderframework,设计Forserver-SideLogic,databasemagement,andapideplupment,thryitalsosupportsfortfortsfrontenddevelopmentwithbladeTemplates。

Laravel vs. Python:探索性能和可扩展性Laravel vs. Python:探索性能和可扩展性Apr 21, 2025 am 12:16 AM

Laravel和Python在性能和可扩展性方面的表现各有优劣。Laravel通过异步处理和队列系统提升性能,但受PHP限制在高并发时可能有瓶颈;Python利用异步框架和强大的库生态系统表现出色,但在多线程环境下受GIL影响。

Laravel vs. Python(与框架):比较分析Laravel vs. Python(与框架):比较分析Apr 21, 2025 am 12:15 AM

Laravel适合团队熟悉PHP且需功能丰富的项目,Python框架则视项目需求而定。1.Laravel提供优雅语法和丰富功能,适合需要快速开发和灵活性的项目。2.Django适合复杂应用,因其“电池包含”理念。3.Flask适用于快速原型和小型项目,提供极大灵活性。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能