ホームページ  >  記事  >  PHPフレームワーク  >  なぜlaravelはファサードを使用するのですか?

なぜlaravelはファサードを使用するのですか?

WBOY
WBOYオリジナル
2022-06-06 16:02:102091ブラウズ

laravelでは、ファサードがアプリケーションのサービスコンテナに「静的」インターフェースを提供できるため、従来の静的メソッドと比較して、ファサードによって提供される「静的」インターフェースは、基礎となるクラスの静的インターフェースと同等です。サービスコンテナのより柔軟でテストしやすい構文を提供できることを表すため、laravel ではファサードが使用されます。

なぜlaravelはファサードを使用するのですか?

#この記事の動作環境: Windows 10 システム、Laravel バージョン 6、Dell G3 コンピューター。

laravel がファサードを使用する理由

Laravel のファサードは、通常、ファサード パターンの基本的な考え方に従います。 Laravel のファサードは、アプリケーションのサービス コンテナに [静的] インターフェイスを提供します。これは、サービス コンテナの基礎となるクラスの [静的代表] に相当し、より柔軟でテストが簡単で洗練された構文を提供できます。

Laravelのファサードではキャッシュなどでよく使います。

Cache::get('key');

もう 1 つの例は、以前よく使用したデータベースと Redis です。

DB::connection('mysql2')->table('db_test')->get()->toArray();
 
Redis::connection('default')->client()->get('test')

いいえ、ファサードはすべて静的メソッドであることがわかりました。しかし、それをクリックすると、このファサード カテゴリには何もないことがわかります。

class Cache extends Facade
{
    protected static function getFacadeAccessor()
    {
        return 'cache';
    }
}

Facade クラスでは、今のところ他のメソッド関数を確認する必要はありません。一番下までスクロールすると、マジック メソッド __callStatic() が見つかります。

public static function __callStatic($method, $args)
{
    $instance = static::getFacadeRoot();
 
    if (! $instance) {
        throw new RuntimeException('A facade root has not been set.');
    }
 
    return $instance->$method(...$args);
}

__callStatic() は、静的に呼び出すときに対応するメソッドが定義されていない場合、__callStatic() メソッドに入ります。たとえば、呼び出した Cache::get() メソッドは、実際には現在どちらでもありません。キャッシュ ファサード クラスまたはその親クラス Facade はこのメソッドを定義するため、直接 __callStatic() に進みます。次に、getFacadeRoot() を通じて現在のファサードのインスタンス オブジェクトを取得し、インスタンス オブジェクトの get() メソッドを呼び出します。

わかりました。実際、面接中に面接官が Laravel でファサード モードを実装する方法を尋ねたら、その核心は __callStatic() マジック メソッドであると自信を持って言えます。では、この特定のインスタンス オブジェクトはどこから来たのでしょうか?読み続けてみましょう。

インスタンス オブジェクト

次に、Facade で特定のインスタンス オブジェクトを取得する方法を見ていきます。ここでサービスコンテナに戻る必要があります。しかし、まずは入り口を見てみましょう。

__callStatic() メソッドでは、特定のインスタンス オブジェクトを取得するために static::getFacadeRoot() メソッドが呼び出されることがわかります。

public static function getFacadeRoot()
{
    return static::resolveFacadeInstance(static::getFacadeAccessor());
}

このメソッドの内容は非常に単純で、他の 2 つのメソッドを呼び出すだけです。getFacadeAccessor() は各ファサード サブクラスに実装されていることに注意してください。たとえば、この例では、キャッシュクラス。インスタンスのエイリアスを返すだけですが、このエイリアスがどこで定義されたか覚えていますか?これは、vendor/laravel/framework/src/Illuminate/Foundation/Application.php の registerCoreContainerAliases() メソッドで定義されているサービス コンテナーで確認しました。

次に、主に注目するのは static::resolveFacadeInstance() メソッドです。名前から、ファサード インスタンスを解決することを意味していることがわかりますが、インスタンス オブジェクトを返さなければ、その名前どおりです。

protected static function resolveFacadeInstance($name)
{
    if (is_object($name)) {
        return $name;
    }
 
    if (isset(static::$resolvedInstance[$name])) {
        return static::$resolvedInstance[$name];
    }
 
    if (static::$app) {
        return static::$resolvedInstance[$name] = static::$app[$name];
    }
}

最初の判断は、オブジェクトが渡された場合、それが直接返されるということです。 2 番目の判断は、現在のインスタンス配列に既に存在する場合、それは再度作成されないというもので、これはフライウェイト モードの効果と同様です。静的メンバー配列に注意してください。それはどういう意味ですか?静的でグローバルに共有されます。つまり、インスタンス オブジェクトが作成された後は、完全なシングルトン状態で他の場所で使用できます。最後の判断は、アプリ、つまりサービス コンテナが存在する場合、サービス コンテナの操作を実行することです。

まず、アプリ属性に値が割り当てられるタイミングを見てみましょう。サービス プロバイダーについて話す場合、カーネルにはブートストラップ属性配列があり、これには RegisterFacades プロバイダーが含まれます。明らかに、これはファサードの登録に使用されるサービス プロバイダーであり、このサービス プロバイダーには次のようなコードが表示されます。

public function bootstrap(Application $app)
{
    Facade::clearResolvedInstances();
 
    Facade::setFacadeApplication($app);
 
    AliasLoader::getInstance(array_merge(
        $app->make('config')->get('app.aliases', []),
        $app->make(PackageManifest::class)->aliases()
    ))->register();
}

このうち、Facade::setFacadeApplication()は、サービスコンテナのApplicationオブジェクトをファサードクラスの静的メンバ変数appに注入します。これも静的であり、グローバルに存在することに注意してください。

次に、resolveFacadeInstance() メソッドに戻ります。

protected static function resolveFacadeInstance($name)
{
    // …………
    // …………
    if (static::$app) {
        return static::$resolvedInstance[$name] = static::$app[$name];
    }
}

ここで何が起こっているのでしょうか? static::$app[$name] を通じてインスタンス オブジェクトを取得するにはどうすればよいですか?興奮したり不安になったりしないで、オブジェクトにそのような配列操作を実行させる方法を考えてみてはいかがでしょうか。前に習ったよ!

これは ArrayAccess インターフェイスです。実装する必要があるいくつかのメソッドにより、オブジェクトを配列のように使用できるようになります。

OK、原理はわかったので、これが当てはまるかどうかを確認し、 Application Vendor/laravel/framework/src/Illuminate/Container/Container.php の親クラスを見つけてみましょう。

class Container implements ArrayAccess, ContainerContract
{
    // …………
    // …………
    public function offsetGet($key)
    {
        return $this->make($key);
    }
    // …………
    // …………
}

本当にベイマックスに似ていますね?これ以上説明する必要はありませんね? make() メソッドについては、前のサービス コンテナで説明しました。

わかりました、残りはあなた次第です。vendor/laravel/framework/src/Illuminate/Foundation/Application.php の registerCoreContainerAliases() メソッドのエイリアスに基づいて Cache の特定の実装クラスを見つけて、分析してください。 get()、set()、forget() およびその他のメソッドの実装と、構成ファイルに従ってさまざまなキャッシュ ストレージ ソリューションがどのように使用されるかを確認します。

[関連する推奨事項: laravel ビデオチュートリアル ]

以上がなぜlaravelはファサードを使用するのですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。