我正在学习Yii2。这是一个我没有用Google搜索过的情况。
我在scraper
的{{1}}数组中注册了一个名为config/console.php
的组件,
此$config['components']
类有一个公共属性scraper
,它是$_client
类。
我尝试使用以下方式设置Goutte\Client
组件,但它无效,Yii2没有将scraper
实例化为$_client
对象。
Goutte\Client
问题:在配置中注入依赖项的工作方式是什么?
答案 0 :(得分:2)
Yii2不会实例化配置数组中第一级以外的对象。换句话说,scraper
将被实例化为对象,但它的属性_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
类中实现,从config实例化对象。最终,此实现执行Yii::configure
:
public static function configure($object, $properties)
{
foreach ($properties as $name => $value) {
$object->$name = $value;
}
return $object;
}
如您所见,所有属性都将分配各自的值,因此_client
将成为数组,而不是对象。
答案 1 :(得分:0)
在guide本身中找到了另一种方法:类targets的属性yii\log\Dispatcher可以用类名或对象初始化。为了使其按预期工作,init方法将被覆盖:
/**
* {@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',
],
],
],
注意:targets是一个数组。但这也可以用单个类/对象来完成。
因此,在您的情况下,这应该是一个解决方案:
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);
}
}
}
btw:通常,变量名称中的下划线前缀用于私有属性。