Als Entwickler versuchen wir immer, neue Wege zu finden, um gut gestalteten und sauberen Code zu schreiben, indem wir neue Stile verwenden, Designmuster verwenden und neue robuste Frameworks ausprobieren. In diesem Artikel werden wir das Abhängigkeitsinjektionsdesign -Muster über die IOC -Komponente von Laravel untersuchen und sehen, wie es unser Design verbessern kann.
Abhängigkeitsinjektion ist ein Begriff, der von Martin Fowler geprägt ist, und es ist der Akt des Einspritzens von Komponenten in Ihre Anwendung. Wie Ward Cunningham sagte:
Abhängigkeitsinjektion ist ein Schlüsselelement der agilen Architektur.
Lassen Sie uns ein Beispiel sehen:
<span>class UserProvider{ </span> <span>protected $connection; </span> <span>public function __construct(){ </span> <span>$this->connection = new Connection; </span> <span>} </span> <span>public function retrieveByCredentials( array $credentials ){ </span> <span>$user = $this->connection </span> <span>->where( 'email', $credentials['email']) </span> <span>->where( 'password', $credentials['password']) </span> <span>->first(); </span> <span>return $user; </span> <span>} </span><span>}</span>
Wenn Sie diese Klasse testen oder verwalten möchten, müssten Sie auf eine reale Datenbank zugreifen und einige Abfragen durchführen. Um zu vermeiden, dies zu tun und die Klasse aus dem Rest zu entziehen, haben Sie eine von drei Optionen, um die Verbindungsklasse zu injizieren, ohne sie direkt zu verwenden. Wenn Sie Komponenten in Ihre Klasse injizieren, können Sie eine der drei Optionen verwenden:
Konstruktorinjektion
<span>class UserProvider{ </span> <span>protected $connection; </span> <span>public function __construct( Connection $con ){ </span> <span>$this->connection = $con; </span> <span>} </span> <span>...</span>
Schnittstelleninjektion
<span>class UserProvider{ </span> <span>protected $connection; </span> <span>public function __construct(){ </span> <span>... </span> <span>} </span> <span>public function setConnection( Connection $con ){ </span> <span>$this->connection = $con; </span> <span>} </span> <span>...</span>
<span>interface ConnectionInjector{ </span> <span>public function injectConnection( Connection $con ); </span><span>} </span> <span>class UserProvider implements ConnectionInjector{ </span> <span>protected $connection; </span> <span>public function __construct(){ </span> <span>... </span> <span>} </span> <span>public function injectConnection( Connection $con ){ </span> <span>$this->connection = $con; </span> <span>} </span><span>}</span>
Wenn wir jetzt unsere Klasse testen, können wir die Abhängigkeitsklasse verspotten und als Parameter übergeben. Jede Klasse muss sich auf eine bestimmte Aufgabe konzentrieren und sollte sich nicht mit der Lösung ihrer Abhängigkeiten befassen. Auf diese Weise haben Sie eine besser fokussierte und wartbare Anwendung.
Wenn Sie mehr über DI erfahren möchten, haben Alejandro Gervassio es in dieser Serie ausführlich und professionell behandelt. Geben Sie diesen Artikeln also unbedingt eine Lektüre an. Was ist mit IOC? IOC (Inversion der Kontrolle) ist nicht erforderlich, um die Abhängigkeitsinjektion zu verwenden, aber es kann Ihnen helfen, Ihre Abhängigkeiten effektiv zu verwalten.
ioc ist eine einfache Komponente, die die Auflöser von Abhängigkeiten bequemer macht. Sie beschreiben Ihre Objekte im Container und jedes Mal, wenn Sie eine Klasse lösen, werden die Abhängigkeiten automatisch injiziert.
laravel ioc ist irgendwie besonders mit seiner Art, Abhängigkeiten zu lösen, wenn Sie nach einem Objekt fragen:
Wir werden ein einfaches Beispiel verwenden, das wir in diesem Artikel verbessern werden.
Die SimpleAuth -Klasse hat eine Abhängigkeit von FilesSessionStorage, sodass unser Code möglicherweise so aussieht:
<span>class UserProvider{ </span> <span>protected $connection; </span> <span>public function __construct(){ </span> <span>$this->connection = new Connection; </span> <span>} </span> <span>public function retrieveByCredentials( array $credentials ){ </span> <span>$user = $this->connection </span> <span>->where( 'email', $credentials['email']) </span> <span>->where( 'password', $credentials['password']) </span> <span>->first(); </span> <span>return $user; </span> <span>} </span><span>}</span>
Dies ist die klassische Art, dies zu tun. Beginnen wir mit der Konstruktorinjektion.
<span>class UserProvider{ </span> <span>protected $connection; </span> <span>public function __construct( Connection $con ){ </span> <span>$this->connection = $con; </span> <span>} </span> <span>...</span>
Jetzt erstellen wir unser Objekt:
<span>class UserProvider{ </span> <span>protected $connection; </span> <span>public function __construct(){ </span> <span>... </span> <span>} </span> <span>public function setConnection( Connection $con ){ </span> <span>$this->connection = $con; </span> <span>} </span> <span>...</span>
Jetzt möchte ich Laravel IOC verwenden, um all das zu verwalten.
Da die Anwendungsklasse die Containerklasse erweitert, können Sie jederzeit über die App -Fassade auf den Container zugreifen.
<span>interface ConnectionInjector{ </span> <span>public function injectConnection( Connection $con ); </span><span>} </span> <span>class UserProvider implements ConnectionInjector{ </span> <span>protected $connection; </span> <span>public function __construct(){ </span> <span>... </span> <span>} </span> <span>public function injectConnection( Connection $con ){ </span> <span>$this->connection = $con; </span> <span>} </span><span>}</span>
Der erste Parameter für die BIND -Methode ist eine eindeutige ID, die an den Container bin Weiter.
Hinweis: Wenn Sie Laravel -Pakete inspizieren, werden Sie, dass manchmal Bindungen wie (Ansicht, View.finder ..).
gruppiert werden.Nehmen wir an, wir möchten vielleicht unseren Sitzungsspeicher auf MySQL wechseln. Unsere Klasse sollte ähnlich sein wie:
<span>class FileSessionStorage{ </span> <span>public function __construct(){ </span> <span>session_start(); </span> <span>} </span> <span>public function get( $key ){ </span> <span>return $_SESSION[$key]; </span> <span>} </span> <span>public function set( $key, $value ){ </span> <span>$_SESSION[$key] = $value; </span> <span>} </span><span>} </span> <span>class SimpleAuth{ </span> <span>protected $session; </span> <span>public function __construct(){ </span> <span>$this->session = new FileSessionStorage; </span> <span>} </span><span>} </span> <span>//creating a SimpleAuth </span><span>$auth = new SimpleAuth();</span>
Jetzt, wo wir die Abhängigkeit geändert haben, müssen wir den SimpleAuth -Konstruktor ändern und ein neues Objekt an den Container binden!
abhängen Bei Abstraktionen.
Module mit hohem Niveau sollten nicht von Modulen mit niedrigem Niveau abhängen. Beide
sollte von Abstraktionen abhängen.
Abstraktionen sollten nicht von Details abhängen. Details solltenRobert C. Martin
Unsere SimpleAuth -Klasse sollte nicht besorgt sein, wie unser Speicher erstellt wird, sondern sollte sich mehr darauf konzentrieren, den Service zu konsumieren.
So können wir unsere Speicherimplementierung abstrahieren:
<span>class SimpleAuth{ </span> <span>protected $session; </span> <span>public function __construct( FileSessionStorage $session ){ </span> <span>$this->session = $session; </span> <span>} </span><span>}</span>
Auf diese Weise können wir einfach eine Instanz der SessionStorage -Schnittstelle implementieren und anfordern:
<span>class UserProvider{ </span> <span>protected $connection; </span> <span>public function __construct(){ </span> <span>$this->connection = new Connection; </span> <span>} </span> <span>public function retrieveByCredentials( array $credentials ){ </span> <span>$user = $this->connection </span> <span>->where( 'email', $credentials['email']) </span> <span>->where( 'password', $credentials['password']) </span> <span>->first(); </span> <span>return $user; </span> <span>} </span><span>}</span>
Wenn wir versuchen, die SimpleAuth -Klasse mit App :: make ('simpauth') durch den Container zu beheben Alle Abhängigkeiten.
<span>class UserProvider{ </span> <span>protected $connection; </span> <span>public function __construct( Connection $con ){ </span> <span>$this->connection = $con; </span> <span>} </span> <span>...</span>
Der Container versucht, die Schnittstelle zu instanziieren. Wir können dies beheben, indem wir eine spezifische Bindung für unsere Schnittstelle erstellen.
<span>class UserProvider{ </span> <span>protected $connection; </span> <span>public function __construct(){ </span> <span>... </span> <span>} </span> <span>public function setConnection( Connection $con ){ </span> <span>$this->connection = $con; </span> <span>} </span> <span>...</span>
Jedes Mal, wenn wir versuchen, die Schnittstelle über den Container zu beheben, erhalten wir eine mySQLSessionStorage -Instanz. Wenn wir unseren Speicherdienst wechseln möchten, können wir einfach die Bindungen aktualisieren.
Hinweis: Wenn Sie sehen möchten, ob eine Klasse an den Container gebunden ist t bereits registriert worden.
Laravel IOC bietet auch App :: Singleton ('ClassName', 'Resolver') für gemeinsame Bindungen.
Sie können auch App :: Instance ('ClassName', 'Instance') verwenden, um eine gemeinsame Instanz zu erstellen.
Wenn der Container die Abhängigkeit nicht beheben kann, wirft er eine ReflexionsException aus, aber wir können die App :: Auflösungs (Schließung) verwenden, um einen bestimmten Typ oder als Form des Sturzes zu lösen.
Hinweis: Wenn Sie einen Resolver für einen bestimmten Typ registrieren, wird auch die Auflösungsmethode aufgerufen, der Wert aus der Bind -Methode wird jedoch zurückgegeben.
Wie immer ist der beste Weg, um etwas zu lernen, den Quellcode zu inspizieren. Laravel IOC ist nur eine Datei und sollte Sie nicht lange brauchen, um alle Funktionen zu durchlaufen. Möchten Sie mehr über Laravel IOC oder IOC im Allgemeinen erfahren? Lass es uns wissen!
Das obige ist der detaillierte Inhalt vonAbhängigkeitsinjektion mit Laravels IOC. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!