首頁 > 後端開發 > php教程 > Laravel 底層 - 一些宏

Laravel 底層 - 一些宏

DDD
發布: 2024-11-07 13:13:03
原創
423 人瀏覽過

Laravel Under The Hood - A Little Bit of Macros

你好 ?

您是否經常希望獲得一個集合或字串助手中不存在的方法?你開始連結方法,結果發現其中一個方法遺失了,結果卻碰壁了。老實說,這是可以理解的;你知道,框架是一刀切的東西。我多次發現自己處於這種情況。每次,在深入研究如何擴展框架之前,我都會檢查我想要擴展的內容是否可宏。但這意味著什麼?這正是我們將要探索的!

WTF 是宏嗎? ?

假設我們有這個 JWT:

$jwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c';
登入後複製
登入後複製

我們需要擷取標題:

str($jwt)
    ->before('.')
    ->fromBase64()
    ->fromJson(); // does not exist ?

//  BadMethodCallException  Method Illuminate\Support\Stringable::fromJson does not exist.
登入後複製
登入後複製

fromJson() 不存在?當然,人們可以簡單地這樣做:

json_decode(str($jwt)->before('.')->fromBase64());
登入後複製
登入後複製

但這有什麼樂趣呢?另外,這是我的文章?

所以,我們需要一個方法來擴充 Stringable 類別。有幾種方法可以做到這一點,但 Laravel 提前思考,它知道開發人員可能想要添加自訂方法,因此它使類別可宏,或者像我喜歡的那樣,可擴展。

如果您檢查 IlluminateSupportStringable 類,您會看到它使用 Macroable 特徵。

讓我們繼續擴展課程。在AppServiceProvider中,加入以下內容:

<?php

namespace App\Providers;

use Illuminate\Support\Stringable;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Stringable::macro('fromJson', function (bool $associative = true) {
            return json_decode($this->value, $associative);
        });
    }
}
登入後複製

現在讓我們重新運行程式碼:

str($jwt)
    ->before('.')
    ->fromBase64()
    ->fromJson();

// ["alg" => "HS256", "typ" => "JWT"]
登入後複製

效果完美嗎?但現在,您可能想知道,這是如何運作的? $this->value 到底是什麼?哈利波特裡發生了什麼事?

揭開魔法的面紗?

我們知道Stringable類別使用Macroable特徵,它提供了macro()方法。讓我們仔細看看它的作用:

// src/Illuminate/Macroable/Traits/Macroable.php

/**
 * Register a custom macro.
 *
 * @param  string  $name
 * @param  object|callable  $macro
 *
 * @param-closure-this static  $macro
 *
 * @return void
 */
public static function macro($name, $macro)
{
    static::$macros[$name] = $macro;
}
登入後複製

這非常簡單,它只是將回調保存到靜態巨集數組中。現在,如果我們進一步檢查該特徵,我們會發現 __call 方法,每次呼叫不存在的方法時都會觸發方法。在我們的例子中,就是 fromJson()。讓我們深入了解:

/**
 * 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(sprintf(
            'Method %s::%s does not exist.', static::class, $method
        ));
    }

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

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

    return $macro(...$parameters);
}
登入後複製

首先,它檢查巨集是否已註冊,fromJson() 就是這種情況,然後從巨集數組中取得回呼(或物件)。現在讓我們來看看魔術,如果巨集是閉包(如我們的例子),它會呼叫bindTo(),它本質上告訴閉包$this應該引用作為第一個參數傳遞的任何內容。在本例中,它是 Stringable 實例,它恰好具有 $value 屬性。

// $this here is the stringable
// $this inside the closure is now referencing the stringable class
$macro->bindTo($this, static::class);
登入後複製

這就是為什麼我們可以做 $this->value。

我們可以做得更好:Mixins?

我還想告訴你一件事!當我們多次擴展同一個類別時,服務提供者可能很快就會變得混亂。我們可以將所有自訂巨集提取到一個名為 Mixin 的類別中。

讓我們建立一個 StringableMixin:

$jwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c';
登入後複製
登入後複製

現在,在 AppServiceProvider 中,我們可以註冊這個 mixin:

str($jwt)
    ->before('.')
    ->fromBase64()
    ->fromJson(); // does not exist ?

//  BadMethodCallException  Method Illuminate\Support\Stringable::fromJson does not exist.
登入後複製
登入後複製

就是這樣!現在我們可以做:

json_decode(str($jwt)->before('.')->fromBase64());
登入後複製
登入後複製

基本上是一樣的,只是比較乾淨一點。

如果您對它的工作原理感到好奇,Macroable 特徵上的 mixin() 方法使用反射 API。它從 Mixin 類別中檢索所有公共方法,期望每個方法傳回一個閉包,然後將閉包註冊為宏,就像我們之前看到的那樣。

糟糕的 IDE?

嗯,正如您所看到的,有很多神奇的事情發生,IDE 不知道定義的巨集。如果您在團隊中工作,其他開發人員也不會知道這些宏,這不好。幸運的是,有一些工具可以幫助您做到這一點。 Laravel IDE 幫助程式包是一個免費開源選項。

您可以安裝該軟體包並產生 _ide_helper.php 文件,然後就可以開始了。

就這樣結束了..

我們的範例相當簡單,但是您可以將巨集推得更遠,因為 Laravel 附帶的大多數常見類別都是可巨集的。例如,您可以新增一個新的 apiResponse() 宏,或者您認為在應用程式邏輯中非常常見且重複次數過多的任何內容。但不要做得太過分。巨集增加了新的複雜性,在團隊中工作時,它們可能會令人困惑。

Soo,每當您感覺應用程式缺少某些內容,但框架本身沒有缺少某些內容時,請使用巨集?

以上是Laravel 底層 - 一些宏的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板