Da in Laravel die Fassade eine „statische“ Schnittstelle für den Service-Container der Anwendung bereitstellen kann, entspricht die von der Fassade bereitgestellte „statische“ Schnittstelle im Vergleich zu herkömmlichen statischen Methoden einem statischen Vertreter in der zugrunde liegenden Klasse des Service-Containers , was eine flexiblere und einfacher zu testende Syntax bieten kann. Verwenden Sie daher Fassaden in Laravel.
Die Betriebsumgebung dieses Artikels: Windows 10-System, Laravel Version 6, Dell G3-Computer.
Fassaden folgen in Laravel grundsätzlich der Grundidee des Fassadenmusters. Die Fassade in Laravel stellt eine [statische] Schnittstelle für den Service-Container der Anwendung bereit, die einem [statischen Vertreter] in der zugrunde liegenden Klasse des Service-Containers entspricht und eine flexiblere, einfacher zu testende und elegantere Syntax bieten kann.
Für die Fassade in Laravel werden wir es häufig verwenden, beispielsweise zum Caching.
Cache::get('key');
Ein weiteres Beispiel ist die Datenbank und Redis, die wir zuvor oft verwendet haben.
DB::connection('mysql2')->table('db_test')->get()->toArray(); Redis::connection('default')->client()->get('test')
Nein, die Fassade besteht ausschließlich aus statischen Methoden. Wenn Sie aber darauf klicken, werden Sie feststellen, dass es in dieser Fassadenkategorie nichts gibt!
class Cache extends Facade { protected static function getFacadeAccessor() { return 'cache'; } }
In der Facade-Klasse müssen wir uns vorerst nicht mit anderen Methodenfunktionen befassen. Scrollen Sie einfach nach unten und Sie werden eine magische Methode finden, __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() bedeutet, dass, wenn beim statischen Aufruf keine entsprechende Methode definiert ist, die von uns aufgerufene Cache::get()-Methode tatsächlich die aktuelle Cache-Fassadenklasse ist Weder seine übergeordnete Klasse Facade noch seine übergeordnete Klasse definieren diese Methode, daher geht sie direkt zu __callStatic(). Anschließend ruft es das Instanzobjekt unserer aktuellen Fassade über getFacadeRoot() ab und ruft dann die Methode get() im Instanzobjekt auf.
Okay, das ist es. Wenn ein Interviewer Sie während des Interviews fragt, wie Sie den Fassadenmodus in Laravel implementieren, können Sie getrost sagen, dass der Kern die magische Methode __callStatic() ist. Woher kommt also dieses spezielle Instanzobjekt? Schauen wir weiter nach unten.
Instanzobjekt
Als nächstes schauen wir uns an, wie man das spezifische Instanzobjekt in Facade erhält. Hier müssen wir zurück zum Servicecontainer gehen. Aber werfen wir zunächst einen Blick auf den Eingang.
In der __callStatic()-Methode werden wir sehen, dass eine static::getFacadeRoot()-Methode aufgerufen wird, um das spezifische Instanzobjekt abzurufen.
public static function getFacadeRoot() { return static::resolveFacadeInstance(static::getFacadeAccessor()); }
Der Inhalt dieser Methode ist sehr einfach, sie ruft lediglich die beiden anderen Methoden auf. Beachten Sie, dass getFacadeAccessor() in jeder unserer Fassadenunterklassen implementiert ist. Im Beispiel ist es beispielsweise in der Cache-Klasse implementiert. Es wird lediglich ein Alias für eine Instanz zurückgegeben. Erinnern Sie sich, wo dieser Alias definiert wurde? Wir haben es im Service-Container gesehen, der in der Methode registerCoreContainerAliases() in Vendor/laravel/framework/src/Illuminate/Foundation/Application.php definiert ist.
Als nächstes schauen wir uns hauptsächlich die Methode static::resolveFacadeInstance() an. Anhand des Namens können wir erkennen, dass es sich um die Lösung der Fassadeninstanz handelt. Wenn dieses Ding kein Instanzobjekt zurückgibt, wird es seinem Namen wirklich nicht gerecht.
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]; } }
Das erste Urteil lautet: Wenn ein Objekt übergeben wird, wird es direkt zurückgegeben. Das zweite Urteil lautet: Wenn im aktuellen Instanzarray bereits eines vorhanden ist, wird es nicht erneut erstellt, was dem Effekt des Fliegengewichtsmodus ähnelt. Beachten Sie, statisches Member-Array! Was bedeutet es? Statisch und global gemeinsam genutzt, d. h. nachdem Ihr Instanzobjekt erstellt wurde, kann es in einem vollständigen Singleton-Zustand an anderer Stelle verwendet werden. Das letzte Urteil lautet: Wenn die App, also unser Service-Container, vorhanden ist, führen Sie den Betrieb des Service-Containers aus.
Werfen wir zunächst einen Blick darauf, wann dem App-Attribut ein Wert zugewiesen wird. Wenn es um Dienstanbieter geht, gibt es im Kernel ein Bootstrappers-Attributarray, das über einen RegisterFacades-Anbieter verfügt. Offensichtlich handelt es sich um einen Dienstanbieter, der zum Registrieren der Fassade verwendet wird. Bei diesem Dienstanbieter werden wir Code wie diesen sehen.
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(); }
Unter anderem injiziert Facade::setFacadeApplication() das Anwendungsobjekt des Servicecontainers in die statische Mitgliedsvariable app der Fassadenklasse. Beachten Sie, dass es auch statisch ist und global existiert.
Dann fahren wir zurück mit der Methode „resolveFacadeInstance()“.
protected static function resolveFacadeInstance($name) { // ………… // ………… if (static::$app) { return static::$resolvedInstance[$name] = static::$app[$name]; } }
Was ist hier los? Wie kann ich ein Instanzobjekt über static::$app[$name] erhalten? Seien Sie nicht aufgeregt, seien Sie nicht ängstlich, denken Sie darüber nach, wie Sie ein Objekt dazu bringen können, solche Array-Operationen auszuführen? Wir haben es schon einmal gelernt!
Dies ist die ArrayAccess-Schnittstelle, und die wenigen Methoden, die sie implementieren muss, ermöglichen die Verwendung von Objekten wie Arrays.
OK, jetzt, da wir das Prinzip kennen, wollen wir sehen, ob dies der Fall ist, und die übergeordnete Klasse von Application Vendor/laravel/framework/src/Illuminate/Container/Container.php finden.
class Container implements ArrayAccess, ContainerContract { // ………… // ………… public function offsetGet($key) { return $this->make($key); } // ………… // ………… }
Sieht es nicht aus wie Baymax? Ich brauche es nicht mehr zu erklären, oder? Die Methode make() wurde im vorherigen Service-Container erläutert.
Okay, der Rest liegt bei Ihnen. Bitte finden Sie die spezifische Implementierungsklasse von Cache basierend auf dem Alias in der Methode registerCoreContainerAliases() in seller/laravel/framework/src/Illuminate/Foundation/Application.php und analysieren Sie dann deren Get (), set(), discover() und andere Methoden, um zu sehen, wie sie gemäß unseren Konfigurationsdateien unterschiedliche Cache-Speicherlösungen verwenden.
【Verwandte Empfehlung: Laravel-Video-Tutorial】
Das obige ist der detaillierte Inhalt vonWarum verwendet Laravel eine Fassade?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!