中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么在Laravel中使用魔術方法

發布時間:2022-09-27 09:25:17 來源:億速云 閱讀:97 作者:iii 欄目:編程語言

本篇內容主要講解“怎么在Laravel中使用魔術方法”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“怎么在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是如何使用的魔術方法

__get()

Laravel中的模型非常特別。它們不將屬性數據存儲為類的直接屬性,而是存儲在protected $attributes 屬性中,該屬性是模型所保存的所有數據的相關數組。

讓我們看看簡單的PHP類和Laravel模型訪問屬性的區別。

<?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'

我們可以看到,上面的PHP和Laravel類的行為完全相同。

然而,在Laravel的例子中,屬性不像普通PHP那樣存儲,而是集中在一個名為$attributes的屬性中。我們仍然設法訪問正確的數據,但是如何訪問呢?

這一切都是可能的,這是因為_get魔術方法。讓我們自己嘗試實現一個簡單的例子。

<?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'

我們做到了! ?

我們需要注意,只有在類中找不到具有匹配名稱的屬性時,才會調用魔術方法_get。這是一種后備方法,當PHP在類中找不到所訪問的屬性時調用。因此,在下面的示例中,根本不會調用魔術方法_get

<?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;

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

laravel/framework

__set()

當試圖設置的屬性沒有在類中聲明時,使用魔術方法_set。讓我們再次看看normal PHP類和Laravel中model模型的區別。

<?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

如我們所見,在此示例中,我們仍然嘗試影響Bob的值,該值在類中實際上不存在但位于屬性$ attributes中。讓我們嘗試使用魔術方法__ 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'

現在我們開始!我們在Laravel中成功實施了__ get__ set魔術方法的基本用法!他們只需幾行代碼就能完成!

請記住,這些魔術方法盡可能簡單,而不必涉及太多細節,因為除了那些還有更多而不僅僅是用例,如果您對它的工作原理感到好奇,我邀請您親自做一些探索! (如果您有任何疑問,也可以隨時在Twitter上與我聯系)

同樣,如果您想進一步挖掘,請在此處鏈接到源代碼

laravel/framework

讓我們繼續最后一個也是最有趣的一個事! ?

__call() & __callStatic()

當調用的方法在類中找不到時,__call()會被調用。 在laravel中,該魔術方法方法使宏在 php 中成為可能。

我不會深入討論宏的所有細節,但如果您感興趣,這里有一篇很好的文章解釋了如何在 Laravel 應用程序中使用它們?

The Magic of Laravel Macros

讓我們試著看看如何編寫一個簡單的宏示例。

<?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中使用魔術方法”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

西畴县| 土默特左旗| 沙河市| 长子县| 台东市| 朔州市| 建平县| 壶关县| 三原县| 宁河县| 尖扎县| 印江| 拜城县| 且末县| 崇左市| 平果县| 铜陵市| 阳原县| 钟山县| 体育| 芜湖县| 龙门县| 兖州市| 油尖旺区| 晋江市| 临武县| 离岛区| 乌苏市| 乌审旗| 磐安县| 滨海县| 桓台县| 石楼县| 东城区| 澜沧| 合水县| 康定县| 荣成市| 赤峰市| 洮南市| 肥东县|