如何在Yii2配置中注入类依赖?

时间:2015-11-22 02:22:35

标签: php dependency-injection yii2

我正在学习Yii2。这是一个我没有用Google搜索过的情况。

我在scraper的{​​{1}}数组中注册了一个名为config/console.php的组件,

$config['components']类有一个公共属性scraper,它是$_client类。

我尝试使用以下方式设置Goutte\Client组件,但它无效,Yii2没有将scraper实例化为$_client对象。

Goutte\Client

问题:在配置中注入依赖项的工作方式是什么?

2 个答案:

答案 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:通常,变量名称中的下划线前缀用于私有属性。