Heim > Artikel > Backend-Entwicklung > Parsen der PHP-Abhängigkeitsinjektion und Umkehrung der Kontrolle
Dieser Artikel stellt hauptsächlich die relevanten Informationen zu PHP Dependency Injection (DI) und Inversion of Control (IoC) vor, die einen bestimmten Referenzwert haben.
Erste Dependency Injection Es geht um die Dasselbe wie die Umkehrung der Kontrolle. Dieses Entwurfsmuster wird verwendet, um die Kopplung zwischen Programmen zu reduzieren. Ich habe es eine Weile studiert und festgestellt, dass es keinen entsprechenden Artikel auf der offiziellen TP-Website gibt Werfen wir einen Blick auf dieses Designmuster und hoffen, der TP-Community etwas Stärke beizutragen.
Verfolgen Sie zunächst nicht die Definition dieses Designmusters, sonst werden Sie definitiv verwirrt sein. Es gibt viele Artikel über Baidu, die alle von a beschrieben werden Aus theoretischer Sicht gibt es viele unbekannte Vokabeln oder es wird durch Java-Code beschrieben, der ebenfalls unbekannt ist.
Egal was passiert, ich habe endlich Klarheit über das Konzept der Abhängigkeitsinjektion aus der Perspektive von PHP.
Angenommen, wir haben hier eine Klasse, die eine Datenbankverbindung verwenden muss. Gemäß der primitivsten Methode können wir diese Klasse wie folgt schreiben:
class example { private $_db; function __construct(){ include "./Lib/Db.php"; $this->_db = new Db("localhost","root","123456","test"); } function getList(){ $this->_db->query("......");//这里具体sql语句就省略不写了 } }
Prozess:
Fügen Sie zuerst die Datenbankklassendatei in den Konstruktor ein.
Übergeben Sie sie dann über die neue Datenbank an die Datenbank. Die Verbindungsinformationen werden instanziiert die db-Klasse;
dann kann die getList-Methode die Datenbankklasse über $this->_db aufrufen, um Datenbankoperationen zu implementieren.
Es scheint, dass wir die gewünschte Funktion erreicht haben, aber dies ist der Beginn eines Albtraums. In Zukunft werden immer mehr Klassen die DB-Komponente If verwenden müssen Sie sind alle so geschrieben. Wenn ja, wenn eines Tages das Datenbankkennwort oder die Datenbankklasse geändert wird, wäre es dann nicht notwendig, alle Klassendateien noch einmal zu ändern?
OK, um dieses Problem zu lösen, haben wir eine Factory-Methode erstellt und die Instanz der Datenbankkomponente über die Factory::getDb()-Methode erhalten:
class Factory { public static function getDb(){ include "./Lib/Db.php"; return new Db("localhost","root","123456","test"); } }
Die Beispielklasse wird:
class example { private $_db; function __construct(){ $this->_db = Factory::getDb(); } function getList(){ $this->_db->query("......");//这里具体sql语句就省略不写了 } }
Ist das perfekt? Denken Sie noch einmal an alle Klassen in der Zukunft, Beispiel1, Beispiel2, Beispiel3 ... Sie müssen eine Db-Instanz über Factory::getDb(); im Konstruktor abrufen. Tatsächlich interagieren Sie direkt mit der Db-Klasse vom Original Die Kopplung mit der Factory-Klasse hilft Ihnen lediglich dabei, die Datenbankverbindungsinformationen zu packen. Wenn sich die Datenbankinformationen ändern, müssen Sie jedoch nur die Factory::getDb()-Methode ändern Der Name muss geändert werden oder die getDb-Methode muss umbenannt werden. Was sollten Sie tun? Natürlich ist diese Art von Nachfrage eigentlich sehr beschissen, aber manchmal gibt es diese Situation:
Wir instanziieren die DB-Komponente nicht aus der Beispielklasse heraus. Wir verlassen uns auf die Injektion von außen . Was bedeutet das? Schauen Sie sich das folgende Beispiel an:
class example { private $_db; function getList(){ $this->_db->query("......");//这里具体sql语句就省略不写了 } //从外部注入db连接 function setDb($connection){ $this->_db = $connection; } } //调用 $example = new example(); $example->setDb(Factory::getDb());//注入db连接 $example->getList();
Auf diese Weise ist die Beispielklasse vollständig von der externen Klasse entkoppelt. Sie können sehen, dass es keine Fabrik gibt in der Db-Klassenmethode oder Db-Klassenfigur. Wir fügen die Verbindungsinstanz direkt hinein, indem wir die setDb-Methode der Beispielklasse von außen aufrufen. Auf diese Weise muss sich das Beispiel nicht darum kümmern, wie die Datenbankverbindung generiert wird.
Dies wird als Abhängigkeitsinjektion bezeichnet. Die Implementierung erstellt keine Abhängigkeitsbeziehung innerhalb des Codes, sondern übergibt sie als Parameter. Dies erleichtert die Wartung unseres Programms, reduziert die Kopplung des Programmcodes und erreicht eine lose Kopplung.
Das ist noch nicht vorbei. Nehmen wir an, dass zusätzlich zu db noch andere externe Klassen in der Beispielklasse verwendet werden. Wir übergeben:
$example->setDb(Factory::getDb());//注入db连接 $example->setFile(Factory::getFile());//注入文件处理类 $example->setImage(Factory::getImage());//注入Image处理类 ...
Schreiben wir endlos so viele Sets? Bist du müde?
ok, um nicht jedes Mal so viele Codezeilen schreiben zu müssen, haben wir eine andere Factory-Methode:
class Factory { public static function getExample(){ $example = new example(); $example->setDb(Factory::getDb());//注入db连接 $example->setFile(Factory::getFile());//注入文件处理类 $example->setImage(Factory::getImage());//注入Image处理类 return $expample; } }
Instanz Beim Wechsel zu Beispiel wird Folgendes angezeigt:
$example=Factory::getExample(); $example->getList();
Es scheint perfekt, aber warum kommt es mir beim ersten Mal so vor, als wäre ich wieder in der Szene Haben Sie die obige Factory-Methode verwendet? Dies ist in der Tat keine gute Lösung, daher wird ein anderes Konzept vorgeschlagen: Container, auch IoC-Container und DI-Container genannt.
Wir haben ursprünglich verschiedene Klassen über die setXXX-Methode eingefügt. Der Code ist zwar sehr lang und es gibt viele Methoden, die jedoch nicht so cool sind die setXXX-Methode, das ist es also. Es ist keine sekundäre Verpackung mit Factory-Methoden erforderlich. Wie können wir also die Abhängigkeitsinjektion implementieren?
Hier führen wir eine Konvention ein: Übergeben Sie einen Parameter namens Di $di im Konstruktor der Beispielklasse wie folgt:
class example { private $_di; function __construct(Di &$di){ $this->_di = $di; } //通过di容器获取db实例 function getList(){ $this->_di->get('db')->query("......");//这里具体sql语句就省略不写了 } } $di = new Di(); $di->set("db",function(){ return new Db("localhost","root","root","test"); }); $example = new example($di); $example->getList();
Di ist der sogenannte IoC-Container, der Instanzen verschiedener Klassen speichert, die wir über $di->set() verwenden können, da er über eine Callback-Funktion übergeben wird wird nicht sofort instanziiert, wenn es gesetzt ist, sondern wird instanziiert, wenn $di->get('db') ausgeführt wird. Ebenso kann der Singleton-Modus auch in das Design der di-Klasse integriert werden.
Auf diese Weise müssen wir nur eine Di-Klasse im globalen Bereich deklarieren, alle Klassen, die injiziert werden müssen, in den Container einfügen und den Container dann als Parameter von an das Beispiel übergeben Der Konstruktor und dann in der Beispielklasse Holen Sie sich die Instanz aus dem Container. Natürlich muss es sich nicht um einen Konstruktor handeln, Sie können auch eine setDi(Di $di)-Methode verwenden, um den Di-Container zu übergeben. Kurz gesagt, die Vereinbarung wird von Ihnen getroffen, Sie müssen sie also nur selbst kennen .
Auf diese Weise wurden Abhängigkeitsinjektions- und Schlüsselcontainerkonzepte eingeführt. Der Rest besteht darin, sie in der Praxis anzuwenden und zu verstehen!
Das obige ist der detaillierte Inhalt vonParsen der PHP-Abhängigkeitsinjektion und Umkehrung der Kontrolle. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!