Dieser Artikel ist das erste Kapitel der Reihe über die Implementierung von PHP-Abhängigkeitsinjektionscontainern.
Lassen Sie uns heute nicht über Container sprechen. Zunächst werden wir anhand einiger konkreter Beispiele das Konzept der Abhängigkeitsinjektion vorstellen, um zu zeigen, welche Probleme dieses Modell lösen kann und welche Vorteile es Entwicklern bringen kann.
Wenn Sie das Konzept der Abhängigkeitsinjektion bereits kennen, können Sie diesen Artikel überspringen.
Abhängigkeitsinjektion ist möglicherweise eines der einfachsten Entwurfsmuster, die ich kenne. In vielen Fällen haben Sie die Abhängigkeitsinjektion möglicherweise unbewusst verwendet. Aber es ist auch eines der am schwierigsten zu erklärenden. Ich denke, ein Teil des Grundes liegt darin, dass den meisten Beispielen, die die Abhängigkeitsinjektion einführen, die praktische Bedeutung fehlt und sie schwer zu verstehen sind. Da PHP hauptsächlich für die Webentwicklung verwendet wird, schauen wir uns zunächst ein einfaches Beispiel für die Webentwicklung an.
HTTP selbst ist ein zustandsloses Verbindungsprotokoll. Um die Anwendung beim Speichern von Benutzerinformationen zu unterstützen, wenn der Client eine WEB-Anfrage initiiert, müssen wir eine Technologie verwenden, um eine Speicherzustandsinteraktion zu erreichen. Der einfachste Weg ist natürlich die Verwendung von Cookies, und ein besserer Weg ist der in PHP integrierte Sitzungsmechanismus.
$_SESSION['language'] = 'fr';
Der obige Code speichert die Benutzersprache in der Sitzungsvariablen mit dem Namen „Sprache“, sodass die Sprache bei nachfolgenden Anforderungen des Benutzers über das globale Array $_SESSION abgerufen werden kann:
$user_language = $_SESSION['language'];
Abhängigkeitsinjektion wird hauptsächlich für die objektorientierte Entwicklung verwendet. Nehmen wir nun an, dass wir eine SessionStorage-Klasse haben, die den PHP-Sitzungsmechanismus kapselt:
class SessionStorage { function __construct($cookieName = 'PHP_SESS_ID') { session_name($cookieName); session_start(); } function set($key, $value) { $_SESSION[$key] = $value; } function get($key) { return $_SESSION[$key]; } // ... }
Es gibt auch eine User-Klasse, die erweiterte Funktionen bietet Die Kapselung:
class User { protected $storage; function __construct() { $this->storage = new SessionStorage(); } function setLanguage($language) { $this->storage->set('language', $language); } function getLanguage() { return $this->storage->get('language'); } // ... }
Der Code ist sehr einfach, und es ist auch sehr einfach, die User-Klasse zu verwenden:
$user = new User(); $user->setLanguage('fr'); $user_language = $user->getLanguage();
Alles ist in Ordnung, es sei denn, Ihr Programm benötigt eine bessere Skalierbarkeit. Angenommen, Sie möchten jetzt den COOKIE-Schlüsselwert ändern, der session_id speichert:
Verwenden Sie beim Erstellen einer SessionStorage-Instanz in der User-Klasse die im SessionStorage-Konstruktor fest codierte Zeichenfolge „SESSION_ID“:
class User { function __construct() { $this->storage = new SessionStorage('SESSION_ID'); } // ... }
Legen Sie eine Konstante außerhalb der Benutzerklasse fest (mit dem Namen STORAGE_SESSION_NAME)
class User { function __construct() { $this->storage = new SessionStorage(STORAGE_SESSION_NAME); } // ... } define('STORAGE_SESSION_NAME', 'SESSION_ID');
Übergeben Sie den Sitzungsnamen über den Parameter im Benutzerklassenkonstruktor
class User { function __construct($sessionName) { $this->storage = new SessionStorage($sessionName); } // ... } $user = new User('SESSION_ID');
Der Sitzungsname wird immer noch über die Parameter im Benutzerklassenkonstruktor übergeben, aber dieses Mal liegen die Parameter in Form eines Arrays vor
class User { function __construct($storageOptions) { $this->storage = new SessionStorage($storageOptions['session_name']); } // ... } $user = new User(array('session_name' => 'SESSION_ID'));
Das oben Genannte Alles auf schlechte Weise.
Das Festcodieren des Sitzungsnamens in der Benutzerklasse löst das Problem nicht wirklich. Wenn Sie den COOKIE-Schlüsselwert, der die Sitzungs-ID speichert, in Zukunft ändern müssen, müssen Sie die Benutzerklasse erneut ändern (die Benutzerklasse sollte sich nicht darum kümmern). über den COOKIE-Schlüsselwert).
Die Art und Weise, Konstanten zu verwenden, ist ebenfalls schlecht, was dazu führt, dass die Benutzerklasse von einer konstanten Einstellung abhängig ist.
Es ist relativ besser, den Sitzungsnamen über die Parameter oder das Array des Benutzerklassenkonstruktors zu übergeben, dies ist jedoch nicht perfekt. Dies beeinträchtigt die Parameter des Benutzerklassenkonstruktors, da die Speicherung der Sitzung nicht der Fall ist Die Benutzerklasse muss sich darum kümmern. Die Benutzerklasse sollte nicht mit ihnen verknüpft sein.
Darüber hinaus gibt es ein weiteres Problem, das nicht einfach zu lösen ist: Wie ändern wir die SessionStorage-Klasse? Hierfür gibt es viele Anwendungsszenarien. Sie möchten beispielsweise eine Sitzungssimulationsklasse zum Testen verwenden oder die Sitzung in einer Datenbank oder einem Speicher speichern. Mit der aktuellen Implementierung ist es schwierig, dies zu tun, ohne die Benutzerklasse zu ändern.
Nun verwenden wir die Abhängigkeitsinjektion. Denken Sie daran, dass wir zuvor das SessionStorage-Objekt innerhalb der User-Klasse erstellt haben. Jetzt ändern wir es und übergeben das SessionStorage-Objekt durch den Konstruktor der User-Klasse.
class User { function __construct($storage) { $this->storage = $storage; } // ... }
Dies ist der klassischste Fall einer Abhängigkeitsinjektion, ohne Ausnahme. Nun gibt es einige kleine Änderungen bei der Verwendung der User-Klasse. Zuerst müssen Sie das SessionStorage-Objekt erstellen.
$storage = new SessionStorage('SESSION_ID'); $user = new User($storage);
Jetzt ist es sehr einfach, das Sitzungsspeicherobjekt zu konfigurieren, und es ist auch sehr einfach, das Sitzungsspeicherobjekt zu ändern. All dies erfordert keine Aktualisierung der Benutzerklasse, wodurch die Kopplung zwischen ihnen verringert wird Business-Kurse.
Die Website von Pico Container beschreibt die Abhängigkeitsinjektion wie folgt:
Abhängigkeitsinjektion ist eine Methode zur Übergabe abhängiger Komponenten an eine Klasse über den Konstruktor, die Methode oder direktes Schreiben der Klasse.
Die Abhängigkeitsinjektion ist also nicht auf die Konstruktorinjektion beschränkt. Werfen wir einen Blick auf mehrere Injektionsmethoden:
Konstruktorinjektion
class User { function __construct($storage) { $this->storage = $storage; } // ... }
Setter-Methodeninjektion
class User { function setSessionStorage($storage) { $this->storage = $storage; } // ... }
Direkte Attributinjektion
class User { public $sessionStorage; } $user->sessionStorage = $storage;
现在,大多数流行的PHP框架都采用了依赖注入的模式实现业务组件间的高内聚低耦合。
// symfony: 构造函数注入的例子 $dispatcher = new sfEventDispatcher(); $storage = new sfMySQLSessionStorage(array('database' => 'session', 'db_table' => 'session')); $user = new sfUser($dispatcher, $storage, array('default_culture' => 'en')); // Zend Framework: setter方式注入的例子 $transport = new Zend_Mail_Transport_Smtp('smtp.gmail.com', array( 'auth' => 'login', 'username' => 'foo', 'password' => 'bar', 'ssl' => 'ssl', 'port' => 465, )); $mailer = new Zend_Mail(); $mailer->setDefaultTransport($transport);
以上就是理解PHP依赖注入容器系列(一) 什么是的内容,更多相关内容请关注PHP中文网(m.sbmmt.com)!