首页 > 解决方案 > Yii2 DI 容器:两次注册同一个类,但构造函数参数不同

问题描述

在我的项目中,我使用在应用程序引导文件中设置的 Yii2 本机依赖注入容器。我想要实现的是两次注入相同的类,但使用不同的构造函数参数:

Yii::$container->set(
    'common\components\ElasticSearchClient',
    [],
    [$elasticSearchServer1Params]
);

Yii::$container->set(
    'common\components\ElasticSearchClient',
    [],
    [$elasticSearchServer2Params]
);

稍后这些弹性搜索客户端类对象应自动注入到其他类中,如下所示:

class SomeClass1
{
    /**
     * @var ElasticSearch
     */
    protected $elasticSearchClient1;

    public function __construct(\common\components\ElasticSearchClient $elasticSearchClient1) {
        $this->elasticSearchClient1 = $elasticSearchClient1;
    }
}

class SomeClass2
{
    /**
     * @var ElasticSearch
     */
    protected $elasticSearchClient2;

    public function __construct(\common\components\ElasticSearchClient $elasticSearchClient2) {
        $this->elasticSearchClient2 = $elasticSearchClient2;
    }
}

那么有可能这样做吗?我应该以某种方式使用 DI 容器别名吗?

标签: phpdependency-injectionyii2

解决方案


您应该为依赖注入容器中的组件使用别名。例如:

向 DI 容器添加组件:

Yii::$container->set(
    'component1',
    [
        'class' => '\common\components\ElasticSearchClient'
    ],
    [$elasticSearchServer1Params]    
);

从 DI 容器中获取组件

$component = Yii::container->get('component1');
$someObject = new SomeClass1($component);

但解决此任务的更明确方法是在创建 SomeClass 之前注册一个 ElasticSearchClient 组件及其配置

// add the component to the container
Yii::$container->set(
    'common\components\ElasticSearchClient',
);

// get the component from container and configure it
Yii::$container->get('common\components\ElasticSearchClient', 
                     [], 
                     [$elasticSearchServer1Params]
);
$someObject = new SomeClass1($component);

此外,您可以在 DI 容器中注册 SomeClass1 和 SomeClass2 以便于创建它们。

$container->set('SomeClass1', function ($container, $params, $config) {
    $searchClient = $contaier->get('common\components\ElasticSearchClient',
                                   [], 
                                   [$elasticSearchServer1Params]
    );
    return new SomeClass1($searchClient);
});

$container->set('SomeClass2', function ($container, $params, $config) {
    $searchClient = $contaier->get('common\components\ElasticSearchClient',
                                   [], 
                                   [$elasticSearchServer2Params]
    );
    return new SomeClass2($searchClient);;
});

推荐阅读