Dependency injection 如何在Yii2配置中注入类依赖关系?
我在学Yii2。有一种情况我还没有用谷歌搜索到答案 我在Dependency injection 如何在Yii2配置中注入类依赖关系?,dependency-injection,configuration,yii2,config,Dependency Injection,Configuration,Yii2,Config,我在学Yii2。有一种情况我还没有用谷歌搜索到答案 我在config/console.php的$config['components']数组中注册了一个名为scraper的组件 这个scraper类有一个公共属性$\u client,它是一个Goutte\client类 我尝试使用以下方法设置scraper组件,但它不起作用,Yii2没有将$\u client实例化为Goutte\client对象 $config = [ 'scraper' => [ 'class'
config/console.php
的$config['components']
数组中注册了一个名为scraper
的组件
这个scraper
类有一个公共属性$\u client
,它是一个Goutte\client
类
我尝试使用以下方法设置scraper
组件,但它不起作用,Yii2没有将$\u client
实例化为Goutte\client
对象
$config = [
'scraper' => [
'class' => 'app\models\Scraper',
'_pageSize' => 10,
'_client' => [ //not working. can not instantiate this property as an object
'class' => 'Goutte\Client'
],
],
//...
]
问题:在配置中注入依赖项的工作方式是什么?Yii2不会实例化配置数组中第一级以外的对象。换句话说,
scraper
将被实例化为一个对象,但它的属性\u client
将被实例化为一个数组['class'=>'Goutte\client']
您应该自己实现这个逻辑:
class Service extends Component
{
private $_client = null;
public $clientClass;
public function getClient()
{
if (null !== $this->_client) {
return $this->_client;
}
$this->_client = new $clientClass;
return $this->_client;
}
}
或者,您可以将Goutte\Client
注册为一个单独的组件,然后Yii将正确地实例化它
更新:
为了澄清,通过yii\base\Configurable
接口从配置中实例化对象,该接口在yii\base\Object
类中实现。最终,此实现执行Yii::configure
:
public static function configure($object, $properties)
{
foreach ($properties as $name => $value) {
$object->$name = $value;
}
return $object;
}
如您所见,所有属性都将被分配各自的值,因此
\u client
将成为一个数组,而不是一个对象。发现了另一种方法:可以使用类名或对象初始化类的属性。要使其按预期工作,方法将被覆盖:
/**
* {@inheritdoc}
*/
public function init()
{
parent::init();
foreach ($this->targets as $name => $target) {
if (!$target instanceof Target) {
$this->targets[$name] = Yii::createObject($target);
}
}
}
这允许对日志组件进行如下配置/初始化:
'log' => [
'class' => 'yii\log\Dispatcher',
'targets' => [
[
'class' => 'yii\log\FileTarget',
],
],
],
注意:这里的目标是一个数组。但是它也可以通过单个类/对象来完成
因此,在您的情况下,这应该是一个解决方案:
namespace app\models;
class Scraper extends ActiveRecord // or extends from anything that actually implements yii\base\Configurable
{
public $_client;
/**
* {@inheritdoc}
*/
public function init()
{
parent::init();
if (!$this->_client instanceof Goutte\Client) {
$this->_client = Yii::createObject($this->_client);
}
}
}
顺便说一句:变量名中的下划线前缀通常用于私有属性。刮板是从模型派生的吗?
\u客户
是公共会员吗?Goutte\Client是完全限定的类名(不是app\Goutte\Client)?Goutte \客户端构造函数没有参数?Scraper是从组件
派生的,$\u客户端
是公共成员。当我在Scraper
class的init()函数中初始化$\u客户机时,所有其他公共基元类型属性都在这个配置文件中设置,它工作正常。如果我在Scraper函数中var\u dump($this->\u client)
,它会显示$this-\u client
是数组(1){[“class”]=>string(13)“Goutte\client”}的数组。Goutte\client
是完全限定的类名,它不需要参数。我可以在Scraper类中通过使用Goutte\Client
导入这个类。您能提供更多的代码(类、名称空间、名称空间用法、配置等)吗?在$config中,我看不到组件
键。我对配置没有太多经验,因此不确定是否可以帮助您。@robsch,是的,我跳过了此代码段的组件
部分,原因是,除此$\u client
属性外,其他所有属性都实例化得很好,所以我只想强调这一部分。谢谢你试着帮我:)这有记录吗?我补充了一些澄清。