成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Laravel 中簡(jiǎn)約而不簡(jiǎn)單的 Macroable 宏指令

itvincent / 1057人閱讀

摘要:方法這個(gè)方法就比較簡(jiǎn)單沒什么復(fù)雜可言,就判斷是否存在宏指令。通常是使用宏指令之前判斷一下。中對(duì)類增加宏指令中很多類都使用了宏這個(gè)比如,我們想為這個(gè)類增加一個(gè)方法,但不會(huì)動(dòng)到里面的代碼。

百度百科的定義:
計(jì)算機(jī)科學(xué)里的宏(Macro),是一種批量處理的稱謂。一般說來,宏是一種規(guī)則或模式,或稱語(yǔ)法替換 ,用于說明某一特定輸入(通常是字符串)如何根據(jù)預(yù)定義的規(guī)則轉(zhuǎn)換成對(duì)應(yīng)的輸出(通常也是字符串)。這種替換在預(yù)編譯時(shí)進(jìn)行,稱作宏展開。

我一開始接觸宏是在大學(xué)上計(jì)算機(jī)基礎(chǔ)課程時(shí),老師講office時(shí)說的。那時(shí)老師介紹宏操作時(shí)沒太在意,只記得這一操作很強(qiáng)大,它能使日常工作變得更容易。

今天我們講講Laravel中的宏操作


首先完整的源碼
getMethods(
            ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED
        );

        foreach ($methods as $method) {
            $method->setAccessible(true);

            static::macro($method->name, $method->invoke($mixin));
        }
    }

    /**
     * Checks if macro is registered.
     *
     * @param  string  $name
     * @return bool
     */
    public static function hasMacro($name)
    {
        return isset(static::$macros[$name]);
    }

    /**
     * Dynamically handle calls to the class.
     *
     * @param  string  $method
     * @param  array   $parameters
     * @return mixed
     *
     * @throws BadMethodCallException
     */
    public static function __callStatic($method, $parameters)
    {
        if (! static::hasMacro($method)) {
            throw new BadMethodCallException("Method {$method} does not exist.");
        }

        if (static::$macros[$method] instanceof Closure) {
            return call_user_func_array(Closure::bind(static::$macros[$method], null, static::class), $parameters);
        }

        return call_user_func_array(static::$macros[$method], $parameters);
    }

    /**
     * Dynamically handle calls to the class.
     *
     * @param  string  $method
     * @param  array   $parameters
     * @return mixed
     *
     * @throws BadMethodCallException
     */
    public function __call($method, $parameters)
    {
        if (! static::hasMacro($method)) {
            throw new BadMethodCallException("Method {$method} does not exist.");
        }

        $macro = static::$macros[$method];

        if ($macro instanceof Closure) {
            return call_user_func_array($macro->bindTo($this, static::class), $parameters);
        }

        return call_user_func_array($macro, $parameters);
    }
}

Macroable::macro方法

public static function macro($name, $macro)
{
    static::$macros[$name] = $macro;
}

很簡(jiǎn)單的代碼,根據(jù)參數(shù)的注釋,$macro可以傳一個(gè)閉包或者對(duì)象,之所以可以傳對(duì)象,多虧了PHP中的魔術(shù)方法

class Father
{
    // 通過增加魔術(shù)方法**__invoke**我們就可以把對(duì)象當(dāng)做閉包來使用了。
    public function __invoke()
    {
        echo __CLASS__;
    }
}

class Child
{
    use IlluminateSupportTraitsMacroable;
}

// 增加了宏指令之后,我們就能調(diào)用 Child 對(duì)象中不存在的方法了
Child::macro("show", new Father);
// 輸出:Father
(new Child)->show();

Macroable::mixin方法

這個(gè)方法是把一個(gè)對(duì)象的方法的返回結(jié)果注入到原對(duì)象中

public static function mixin($mixin)
{
    // 通過反射獲取該對(duì)象中所有公開和受保護(hù)的方法
    $methods = (new ReflectionClass($mixin))->getMethods(
        ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED
    );

    foreach ($methods as $method) {
        // 設(shè)置方法可訪問,因?yàn)槭鼙Wo(hù)的不能在外部調(diào)用
        $method->setAccessible(true);
        
        // 調(diào)用 macro 方法批量創(chuàng)建宏指令
        static::macro($method->name, $method->invoke($mixin));
    }
}

// 實(shí)際使用
class Father
{
    public function say()
    {
        return function () {
            echo "say";
        };
    }

    public function show()
    {
        return function () {
            echo "show";
        };
    }

    protected function eat()
    {
        return function () {
            echo "eat";
        };
    }
}

class Child
{
    use IlluminateSupportTraitsMacroable;
}

// 批量綁定宏指令
Child::mixin(new Father);

$child = new Child;
// 輸出:say
$child->say();
// 輸出:show
$child->show();
// 輸出:eat
$child->eat();

在上面的代碼可以看出mixin可以將一個(gè)類的方法綁定到宏類中。需要注意的就是,方法必須是返回一個(gè)閉包類型。

Macroable::hasMacro方法

public static function hasMacro($name)
{
    return isset(static::$macros[$name]);
}

這個(gè)方法就比較簡(jiǎn)單沒什么復(fù)雜可言,就判斷是否存在宏指令。通常是使用宏指令之前判斷一下。

Macroable::__callMacroable::__callStatic方法

正是由于這兩個(gè)方法,我們才能進(jìn)行宏操作,兩個(gè)方法除了執(zhí)行方式不同,代碼大同小異。這里講一下__call

public function __call($method, $parameters)
{
    // 如果不存在這個(gè)宏指令,直接拋出異常
    if (! static::hasMacro($method)) {
        throw new BadMethodCallException("Method {$method} does not exist.");
    }

    // 得到存儲(chǔ)的宏指令
    $macro = static::$macros[$method];

    // 閉包做一點(diǎn)點(diǎn)特殊的處理
    if ($macro instanceof Closure) {
        return call_user_func_array($macro->bindTo($this, static::class), $parameters);
    }

    // 不是閉包,比如對(duì)象的時(shí)候,直接通過這種方法運(yùn)行,但是要確保對(duì)象有`__invoke`方法
    return call_user_func_array($macro, $parameters);
}


class Child
{
    use IlluminateSupportTraitsMacroable;

    protected $name = "father";
}

// 閉包的特殊處理,需要做的就是綁定 $this, 如
Child::macro("show", function () {
    echo $this->name;
});

// 輸出:father
(new Child)->show();

在上面的操作中我們綁定宏時(shí),在閉包中可以通過$this來調(diào)用Child的屬性,是因?yàn)樵?b>__call方法中我們使用Closure::bindTo方法。

官網(wǎng)對(duì)Closure::bindTo的解釋:復(fù)制當(dāng)前閉包對(duì)象,綁定指定的$this對(duì)象和類作用域。
Laravel 中對(duì)類增加宏指令

Laravel中很多類都使用了宏這個(gè)trait

比如IlluminateFilesystemFilesystem::class,我們想為這個(gè)類增加一個(gè)方法,但不會(huì)動(dòng)到里面的代碼。

我們只需要到AppProvidersAppServiceProvider::register方法增加宏指令(你也可以專門新建一個(gè)服務(wù)提供者專門處理)

然后增加一條測(cè)試路由,測(cè)試我們新增加的方法

然后打開瀏覽器運(yùn)行,你就會(huì)發(fā)現(xiàn),我們的代碼可以正常的運(yùn)行了并輸出結(jié)果了


原文地址

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/29011.html

相關(guān)文章

  • Laravel Model 利用 Macroable 為數(shù)據(jù)模型添加能力

    摘要:利用當(dāng)前類沒有這個(gè)函數(shù)的時(shí)候執(zhí)行這個(gè)函數(shù)名注冊(cè)的回調(diào)。使用有了這個(gè)那么我們添加到模型中,就可以使用宏能力為其動(dòng)態(tài)添加函數(shù)了這樣,我們可以直接拿到用戶發(fā)布的所有問題了。 【摘要】簡(jiǎn)單的說一下宏能力,這個(gè)類是 IlluminateSupportTraitsMacroable 其中利用重載實(shí)現(xiàn)了可以定義宏的功能,即通過 macro 靜態(tài)方法添加回調(diào),并定義一個(gè)名字。利用 __call 當(dāng)前類...

    zhangfaliang 評(píng)論0 收藏0
  • Debugging collections(譯)

    摘要:注本文是翻譯寫的關(guān)于調(diào)試技巧,讀完以后很實(shí)用,分享給大家閱讀過程中,翻譯有錯(cuò)誤的希望大家指正原文鏈接最近我一直在使用的,如果你還不了解,我簡(jiǎn)單說下一個(gè)集合就是一個(gè)功能強(qiáng)大的數(shù)組有很多強(qiáng)大處理其內(nèi)部數(shù)據(jù)的函數(shù)但是唯一讓我頭疼的地方是如何調(diào)試的 注:本文是翻譯Freek Van der Herten寫的關(guān)于Collection調(diào)試技巧,,讀完以后很實(shí)用,分享給大家.閱讀過程中,翻譯有錯(cuò)誤的...

    lunaticf 評(píng)論0 收藏0
  • [譯] Laravel-Excel 3.0 文檔

    摘要:事件將通過添加關(guān)注來激活。自動(dòng)注冊(cè)事件監(jiān)聽器通過使用,你可以自動(dòng)注冊(cè)事件監(jiān)聽器,而不需要使用。你可以自由使用這個(gè)宏,或者創(chuàng)造你自己的語(yǔ)法以上例子可作對(duì)于方法可查看文檔測(cè)試測(cè)試下載測(cè)試存儲(chǔ)導(dǎo)出測(cè)試隊(duì)列導(dǎo)出 Basics 最簡(jiǎn)單的導(dǎo)出方法是創(chuàng)建一個(gè)自定義的導(dǎo)出類, 這里我們使用發(fā)票導(dǎo)出作為示例. 在 App/Exports 下創(chuàng)建一個(gè) InvoicesExport 類 namespace...

    canopus4u 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<