ここまで、最初の 2 つの記事の例は、依存関係注入の実装を理解するのに非常に役立ちます。次に、Symfony 2 サービス コンテナの実装について詳しく説明します。
Symfony の依存関係注入コンテナーは、sfServiceContainer というクラスによって管理されます。
Symfony コンテナーは、独立したコンポーネントとして存在できます。Symfony の公式 Subversion リポジトリは、http://svn.symfony-project.com /components/ からダウンロードできます。 dependency_injection/trunk/
。このコンポーネントは現在も継続的に反復開発中であるため、いつでも更新される可能性があることは注目に値します (2009 年にそう言われていましたが、現在は停止しているようです)。
Symfony の設計哲学によれば、どのサービスもコンテナによって管理されるオブジェクトにすることができます。前の記事で紹介した Zend_Mail の例では、 mailer と mail_transport の 2 つのオブジェクトがあります
class Container { static protected $shared = array(); 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() { 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 クラスが Symfony の sfServiceContainer クラスを継承している場合、コードはもう少し単純になります
class Container extends sfServiceContainer { static protected $shared = array(); protected function getMailTransportService() { return new Zend_Mail_Transport_Smtp('smtp.gmail.com', array( 'auth' => 'login', 'username' => $this['mailer.username'], 'password' => $this['mailer.password'], 'ssl' => 'ssl', 'port' => 465, )); } protected function getMailerService() { if (isset(self::$shared['mailer'])) { return self::$shared['mailer']; } $class = $this['mailer.class']; $mailer = new $class(); $mailer->setDefaultTransport($this->getMailTransportService()); return self::$shared['mailer'] = $mailer; } }
観察すると、構造は省略されています機能とパラメータの構成管理。
しかし、それだけではありません。sfServiceContainer は強力で簡潔なインターフェースを提供します。インターフェースを使用する際に注意すべき点がいくつかあります。
1. サービスを取得するメソッドの名前には Service を付ける必要があります。通常、メソッドの名前は get で始まり Service で終わることに同意します。各サービスには固有のロゴがあります。ロゴは通常、接尾辞と接尾辞を除いたメソッド名をアンダースコアで区切ったものです。 getMailTransportService() メソッドが定義されている場合、サービス名は mail_transport
2 です。このメソッドは保護されたタイプであるため、メソッドを直接呼び出してサービスを取得することはできません。コンテナを使用してサービスを取得する方法については後ほど紹介します。
3. コンテナーに配列としてアクセスして、渡されたパラメーターを取得できます。例: $this[‘mailer.class’]
サービス マークは一意である必要があり、文字、数字、「_」、「.」のみで構成できます。 「.」は名前空間として使用できます (mail.mailer や mail.transport など)。
それでは、この新しいコンテナの使い方を見てみましょう
require_once 'PATH/TO/sf/lib/sfServiceContainerAutoloader.php'; sfServiceContainerAutoloader::register(); $sc = new Container(array( 'mailer.username' => 'foo', 'mailer.password' => 'bar', 'mailer.class' => 'Zend_Mail', )); $mailer = $sc->mailer;
ContainerクラスはsfServiceContainerを継承しているため、インターフェースが非常にすっきりしています。
サービスは統合インターフェースを通じてアクセスされます
if ($sc->hasService('mailer')) { $mailer = $sc->getService('mailer'); } $sc->setService('mailer', $mailer);
より簡単な方法は、サービスが属性を通じてアクセスされることです
if (isset($sc->mailer)) { $mailer = $sc->mailer; } $sc->mailer = $mailer;パラメータは統一インターフェースを通じてアクセスされます
パラメータは配列などのコンテナを通じてアクセスすることもできます
if (!$sc->hasParameter('mailer_class')) { $sc->setParameter('mailer_class', 'Zend_Mail'); } echo $sc->getParameter('mailer_class'); // Override all parameters of the container $sc->setParameters($parameters); // Adds parameters $sc->addParameters($parameters);
はい、コンテナをすべてのサービスを横断するイテレータとして考えてください
if (!isset($sc['mailer.class'])) { $sc['mailer.class'] = 'Zend_Mail'; } $mailerClass = $sc['mailer.class'];
管理するサービスがそれほど多くない場合は、それでも多くの基本作業を実行し、多くのコードをコピーする必要がありますが、 sfServiceContainer の使用が非常に便利であることは認めざるを得ません。
管理するサービスの数がますます多くなると、サービスを記述するより良い方法が必要になります。
これが、ほとんどの場合、sfServiceContainer クラスを直接使用しない理由です。それでも、これについては時間をかけて説明する必要があります。これは、Symfony の依存関係注入コンテナーの重要な基礎であるためです。
上記は、PHP 依存性注入コンテナー シリーズ (3) Symfony を理解するための内容です。さらに関連する内容については、PHP 中国語 Web サイト (www.php.cn) に注目してください。