LoginSignup
13
9

More than 5 years have passed since last update.

Ray.Di コンストラクタ束縛

Last updated at Posted at 2015-04-24

コンストラクタ束縛

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束縛よりクリーンに記述でき、この例のような動的な束縛にも向いています。

13
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
9