Heim >php教程 >PHP开发 >Grundlegendes zur PHP-Dependency-Injection-Container-Serie (2) Was Sie brauchen

Grundlegendes zur PHP-Dependency-Injection-Container-Serie (2) Was Sie brauchen

黄舟
黄舟Original
2016-12-28 10:24:441583Durchsuche

Im vorherigen Artikel haben wir einen spezifischen Web-Fall verwendet, um die Abhängigkeitsinjektion zu veranschaulichen. Heute werden wir über den Abhängigkeitsinjektionscontainer (Container) sprechen. Beginnen wir zunächst mit einer wichtigen Aussage:

Big Most of Wenn Sie die Abhängigkeitsinjektion zum Entkoppeln von Komponenten verwenden, benötigen Sie keinen Container.

Aber wenn Sie viele verschiedene Objekte verwalten und mit komplexen Abhängigkeiten zwischen Objekten umgehen möchten, sind Container sehr nützlich.
Erinnern Sie sich an das Beispiel im ersten Artikel? Bevor Sie ein Benutzerobjekt erstellen, müssen Sie zunächst ein SessionStorage-Objekt erstellen. Das ist keine große Sache, aber ich möchte dennoch sagen, dass dies daran liegt, dass Sie die Objekte, von denen es abhängt, genau kennen, bevor Sie das benötigte Objekt erstellen. Wenn es viele Objekte gibt und die Abhängigkeiten kompliziert sind (vorausgesetzt, die SessionStorage-Klasse hängt von der Cache-Klasse ab, die Cache-Klasse hängt von der Dateiklasse und der InputFilter-Klasse ab und die Dateiklasse hängt von der stdio-Klasse ab), dann ist dies der Fall ein Problem. . . .

$storage = new SessionStorage('SESSION_ID');
$user = new User($storage);

In nachfolgenden Artikeln stellen wir vor, wie man Container in Symfony 2 implementiert. Aber um Container einfach und klar zu erklären, lassen wir Symfony vorerst außer Acht. Im Folgenden wird ein Beispiel im Zend Framework zur Veranschaulichung verwendet:
Die Zend_Mail-Klasse von Zend Framework vereinfacht die E-Mail-Verwaltung. Sie verwendet standardmäßig die Funktion mail() von PHP, um E-Mails zu senden, aber ihre Flexibilität ist nicht gut. Glücklicherweise kann dieses Verhalten durch die Bereitstellung einer Transportklasse leicht geändert werden.
Der folgende Code zeigt, wie man die Zend_Mail-Klasse erstellt und ein Gmail-Konto zum Senden von E-Mails verwendet.

$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);

Der Dependency-Injection-Container ist eine große Klasse, die verschiedene Elemente, die er verwaltet, instanziieren und konfigurieren kann Klassen. Dazu muss es die Parameter und Abhängigkeiten der Konstruktormethoden dieser Klassen kennen.
Das Folgende ist ein hartcodierter Container, der immer noch die zuvor erwähnte Arbeit zum Abrufen des Zend_Mail-Objekts implementiert:

class Container
{
  public function getMailTransport()
  {
    return new Zend_Mail_Transport_Smtp('smtp.gmail.com', array(
      'auth'     => 'login',
      'username' => 'foo',
      'password' => 'bar',
      'ssl'      => 'ssl',
      'port'     => 465,
    ));
  }
  public function getMailer()
  {
    $mailer = new Zend_Mail();
    $mailer->setDefaultTransport($this->getMailTransport());
    return $mailer;
  }
}
//容器的使用也很简单
$container = new Container();
$mailer = $container->getMailer();

Wenn Sie den Container verwenden und ein Zend_Mail-Objekt benötigen, tun Sie dies nicht Sie müssen die Details der Erstellung kennen, da alle Details der Erstellung einer Objektinstanz in den Container integriert sind. Die Abhängigkeit von Zend_Mail von der Mail_Transport-Klasse kann auch automatisch über den Container in das Zend_Mail-Objekt eingefügt werden.
Das Abrufen abhängiger Objekte wird hauptsächlich durch getMailTransport() implementiert. Die Leistung des Containers wird durch diesen einfachen Get-Aufruf erreicht.
Aber wenn Sie schlau sind, müssen Sie das Problem entdeckt haben. Der Container enthält harte Codierungen (z. B. die Konto- und Passwortinformationen zum Senden von E-Mails usw.). Wir müssen also noch einen Schritt weiter gehen und dem Container Parameter hinzufügen, um den Container nützlicher zu machen.

class Container
{
  protected $parameters = array();
  public function __construct(array $parameters = array())
  {
    $this->parameters = $parameters;
  }
  public function getMailTransport()
  {
    return new Zend_Mail_Transport_Smtp('smtp.gmail.com', array(
      'auth'     => 'login',
      'username' => $this->parameters['mailer.username'],
      'password' => $this->parameters['mailer.password'],
      'ssl'      => 'ssl',
      'port'     => 465,
    ));
  }
  public function getMailer()
  {
    $mailer = new Zend_Mail();
    $mailer->setDefaultTransport($this->getMailTransport());
    return $mailer;
  }
}

Jetzt können Sie das Konto und das Passwort zum Senden von E-Mails einfach über die Parameter des Containerkonstruktors ändern

$container = new Container(array(
  'mailer.username' => 'foo',
  'mailer.password' => 'bar',
));
$mailer = $container->getMailer();

Wenn Sie der Meinung sind, dass die Zend_Mail-Klasse die aktuellen Anforderungen nicht erfüllen kann ( B. beim Testen, müssen Sie einige Protokolle erstellen. Wenn Sie die E-Mail-Sendeklasse einfach ändern möchten, können Sie den Klassennamen auch über die Parameter des Containerkonstruktors übergeben.

class Container
{
  // ...
  public function getMailer()
  {
    $class = $this->parameters['mailer.class'];
    $mailer = new $class();
    $mailer->setDefaultTransport($this->getMailTransport());
    return $mailer;
  }
}
$container = new Container(array(
  'mailer.username' => 'foo',
  'mailer.password' => 'bar',
  'mailer.class'    => 'MyTest_Mail',
));
$mailer = $container->getMailer();

Abschließend noch eine Überlegung Damit Kunden beim Abrufen des Mailer-Objekts nicht jedes Mal eine neue Instanz erstellen müssen (Overhead), sollte der Container jedes Mal dieselbe Objektinstanz bereitstellen.
Daher verwendet das Programm das geschützte statische Array $shared, um das erste instanziierte Objekt zu speichern. Wenn der Benutzer in Zukunft den Mailer erhält, wird das erste instanziierte Objekt zurückgegeben

class Container
{
  static protected $shared = array();
  // ...
  public function getMailer()
  {
    if (isset(self::$shared['mailer']))
    {
      return self::$shared['mailer'];
    }
    $class = $this->parameters['mailer.class'];
    $mailer = new $class();
    $mailer->setDefaultTransport($this->getMailTransport());
    return self::$shared['mailer'] = $mailer;
  }
}

Container kapseln Zu diesen Grundfunktionen gehört die Instanziierung und Konfiguration von Objekten. Diese Objekte selbst wissen nicht, dass sie vom Container verwaltet werden, und können die Existenz des Containers ignorieren. Aus diesem Grund kann der Container jede beliebige PHP-Klasse verwalten. Es wäre besser, wenn das Objekt selbst die Abhängigkeitsinjektion verwendet, um Abhängigkeiten zu verarbeiten, aber das ist natürlich nicht notwendig.

Aber das Erstellen und Warten von Behältern von Hand kann schnell zum Albtraum werden. Der folgende Artikel beschreibt, wie Symfony 2 Container implementiert.

Das Obige ist, was Sie zum Verständnis der PHP-Abhängigkeitsinjektionscontainerserie (2) benötigen. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (www.php.cn).


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn