コンストラクタ束縛
Ray.Di
には@Inject
アノテーションの付いていないサードパーティーのクラスにも使用できるコンストラクタ束縛 (toConstructor
binding)という束縛があります。
実装例
複数のオブジェクトの利用でそれぞれは同じクラスでインスタンス化されていますが、別のオブジェクトのケースがあります。例えば接続先DBの違う複数のDBオブジェクトなどです。これは一般に ロボットの足問題 (robot legs problem)として知られる問題です。
要件
設定の異なるSolrClientを利用するためのSolarModule
を作成することを考えます。SolarModule
のコンストラクタに渡す設定値は以下のとおり。
$config = [
'foo' => ['port' => 8080],
'bar' => ['port' => 8081]
]
bar
の設定でつくられたSolrClient
は以下のセッターメソッドで受け取れるようにします。
/**
* @Inject
* @Named("bar")
*/
public function setBarClient(\SolrClient $solrClient)
{
実装コード
<?php
require dirname(__DIR__) . '/vendor/autoload.php';
use Ray\Di\AbstractModule;
use Ray\Di\Di\Inject;
use Ray\Di\Di\Named;
use Ray\Di\Injector;
class SolarModule extends AbstractModule
{
private $config;
public function __construct(array $config)
{
$this->options = $config;
}
/**
* {@inheritdoc}
*/
protected function configure()
{
foreach ($this->config as $name => $option) {
$optionName = "options.solr.{$name}";
// SolrClientのコンストラクタ引数$clientOptionsに"options.solr.{$name}"という名前を動的につけます。
$this->bind(\SolrClient::class)->annotatedWith($name)->toConstructor(
\SolrClient::class,
"clientOptions=$optionName"
);
// "options.solr.{$name}"に値を直接束縛しています。
$this->bind()->annotatedWith($optionName)->toInstance($option);
}
}
}
class IndexPage
{
/**
* @var \SolrClient
*/
private $fooSolrClient;
/**
* @var \SolrClient
*/
private $barSolrClient;
/**
* @Inject
* @Named("foo")
*/
public function setFooClient(\SolrClient $solrClient)
{
$this->fooSolrClient = $solrClient;
}
/**
* @Inject
* @Named("bar")
*/
public function setBarClient(\SolrClient $solrClient)
{
$this->barSolrClient = $solrClient;
}
public function showOptions()
{
var_dump($this->fooSolrClient->getOptions()['port']);
var_dump($this->barSolrClient->getOptions()['port']);
}
}
$config = [
'foo' => ['port' => 8080],
'bar' => ['port' => 8081]
];
$injector = new Injector(new SolarModule($config));
/** @var $page IndexPage */
$page = $injector->getInstance(IndexPage::class);
$page->showOptions();
//int(8080)
//int(8081)
結論
toConstructor
束縛は依存の構造を明らかにするためProvider
束縛よりクリーンに記述でき、この例のような動的な束縛にも向いています。