前の記事では、依存性注入を説明するために特定の Web ケースを使用しました。今日は依存性注入コンテナー (コンテナー) について説明します。まず、重要な点から始めましょう:
ほとんどの場合、コンポーネントを分離するための依存関係注入では、コンテナーを使用する必要はありません。
しかし、多くの異なるオブジェクトを管理し、オブジェクト間の複雑な依存関係に対処したい場合には、コンテナーが非常に役立ちます。
最初の記事の例を覚えていますか? User オブジェクトを作成する前に、まず SessionStorage オブジェクトを作成する必要があります。これは大したことではありませんが、これは、必要なオブジェクトを作成する前に、そのオブジェクトが依存するオブジェクトを明確に知っているためであると言いたいと思います。オブジェクトが多く、依存関係が複雑な場合 (SessionStorage クラスがキャッシュ クラスに依存し、キャッシュ クラスがファイル クラスと inputFilter クラスに依存し、ファイル クラスが stdio クラスに依存すると仮定すると)、次のようになります。問題。 。 。 。
$storage = new SessionStorage('SESSION_ID'); $user = new User($storage);
次の記事では、Symfony 2 でコンテナを実装する方法を紹介します。ただし、コンテナについて簡単かつ明確に説明するために、ここでは Symfony を無視します。以下では、Zend Framework の例を使用して説明します。
Zend Framework の Zend_Mail クラスは、デフォルトで PHP の mail() 関数を使用して電子メールを送信しますが、その柔軟性は良好ではありません。ありがたいことに、この動作はトランスポート クラスを提供することで簡単に変更できます。
次のコードは、Zend_Mail クラスを作成し、Gmail アカウントを使用して電子メールを送信する方法を示しています
$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);
依存関係注入コンテナー (Dependency Injection Container) は、管理するさまざまなコンポーネントとクラスをインスタンス化して構成できる大規模なクラスです。これを行うには、これらのクラスのコンストラクター メソッドのパラメーターと依存関係を知っている必要があります。
以下は、前述の Zend_Mail オブジェクトを取得する作業を実装したハードコードされたコンテナです:
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();
コンテナを使用するとき、Zend_Mail オブジェクトを取得する必要がある場合、その作成の詳細を知る必要はありませんオブジェクト インスタンスの作成に関する詳細はすべてコンテナーに組み込まれているためです。 Zend_Mail の Mail_Transport クラスへの依存関係は、コンテナを通じて Zend_Mail オブジェクトに自動的に注入することもできます。
依存オブジェクトの取得は主に getMailTransport() によって実装され、コンテナーの機能はこの単純な get 呼び出しによって実現されます。
しかし、賢明な方なら、コンテナ内にハードコード (メール送信用のアカウントやパスワード情報など) があることに気づいたはずです。したがって、さらに一歩進んで、コンテナにパラメータを追加して、コンテナをより使いやすくする必要があります。
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; } }
これで、コンテナ コンストラクターのパラメータを通じてメール送信用のアカウントとパスワードを簡単に切り替えることができます
$container = new Container(array( 'mailer.username' => 'foo', 'mailer.password' => 'bar', )); $mailer = $container->getMailer();
Zend_Mail クラスが現在のニーズを満たせないと思われる場合 (たとえば、テストする場合、いくつかのログを作成する必要があります) )、メール送信クラスを簡単に切り替えたい場合も同様です。クラス名はコンテナコンストラクターのパラメータで渡すことができます
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();
最後に、顧客がメーラーオブジェクトを取得するたびに再インスタンス化する必要がないことを考慮すると、 (オーバーヘッドを占有する)、コンテナは毎回同じオブジェクト インスタンスを提供する必要があります。
したがって、プログラムは保護された静的配列 $shared を使用して、将来ユーザーがメーラーを取得すると、最初のインスタンス化されたオブジェクトが返されます。コンテナはオブジェクトのインスタンス化と構成を含めて管理する必要があります。これらのオブジェクト自体は、コンテナーによって管理されていることを認識せず、コンテナーの存在を無視できます。これが、コンテナーが任意の PHP クラスを管理できる理由です。オブジェクト自体が依存関係を処理するために依存関係注入を使用する方が良いですが、もちろんこれは必須ではありません。
しかし、コンテナーを手動で作成して維持することは、すぐに悪夢に変わる可能性があります。次の記事では、Symfony 2 がコンテナを実装する方法について説明します。
上記は、PHP 依存関係注入コンテナー シリーズ (2) を理解するために必要なものです。その他の関連コンテンツについては、PHP 中国語 Web サイト (www.php.cn) に注目してください。