Свойства компонента в его конструкторе

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
shkarbatov
Сообщения: 423
Зарегистрирован: 2012.12.10, 14:19
Откуда: Россия

Свойства компонента в его конструкторе

Сообщение shkarbatov »

Всем привет. Делаю сейчас компонент для Yii, компонент не наследуется от Component и соответственно не наследуется от Object.

Мне необходимо получить в его конструкторе, параметры которые пользователь прописывает в конфигах, в компоненте, то есть которые в самом объекте доступны как $this->...

В DIContainer есть метод, который занимается созданием объектов:

Код: Выделить всё

protected function build($class, $params, $config)
{
    /* @var $reflection ReflectionClass */
    list ($reflection, $dependencies) = $this->getDependencies($class);

    foreach ($params as $index => $param) {
        $dependencies[$index] = $param;
    }

    if (!empty($dependencies) && is_a($class, 'yii\base\Object', true)) {
        // set $config as the last parameter (existing one will be overwritten)
        $dependencies[count($dependencies) - 1] = $config;
        $dependencies = $this->resolveDependencies($dependencies, $reflection);
        return $reflection->newInstanceArgs($dependencies);
    } else {
        $dependencies = $this->resolveDependencies($dependencies, $reflection);
        $object = $reflection->newInstanceArgs($dependencies);
        foreach ($config as $name => $value) {
            $object->$name = $value;
        }
        return $object;
    }
} 
Вопросы:

1) Почему используется только для класса, который был унаследован от Object?

Код: Выделить всё

$dependencies[count($dependencies) - 1] = $config; 
2) Можно ли как-то получить свойства компонента, не вынося их в конфиги всего проекта, и не обращаясь на прямую?

Код: Выделить всё

Yii::$app->components->myComponent->component_variable
Так, как если разработчик на проекте назовет компонент не myComponent, то все поломается.
shkarbatov
Сообщения: 423
Зарегистрирован: 2012.12.10, 14:19
Откуда: Россия

Re: Свойства компонента в его конструкторе

Сообщение shkarbatov »

Спасибо, у меня была предыдущая версия.
Обновился, завелось.
shkarbatov
Сообщения: 423
Зарегистрирован: 2012.12.10, 14:19
Откуда: Россия

Re: Свойства компонента в его конструкторе

Сообщение shkarbatov »

А зачем было сделано через интерфейс, почему не сделать передачу конфигов в конструктор по умолчанию?
shkarbatov
Сообщения: 423
Зарегистрирован: 2012.12.10, 14:19
Откуда: Россия

Re: Свойства компонента в его конструкторе

Сообщение shkarbatov »

Есть идеи?
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Свойства компонента в его конструкторе

Сообщение ElisDN »

Ну там же в коде выше if если наследуется и else если нет.
shkarbatov
Сообщения: 423
Зарегистрирован: 2012.12.10, 14:19
Откуда: Россия

Re: Свойства компонента в его конструкторе

Сообщение shkarbatov »

ElisDN писал(а):Ну там же в коде выше if если наследуется и else если нет.
Это я понял :)

Вопрос в другом, зачем это было делать, зачем добавлять этот if, почему не сделать без него, если эти данные не нужны в конструкторе, то можно просто их не получать и ошибки никакой не будет.
А так в компоненте на лицо зависимость от Yii.
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Свойства компонента в его конструкторе

Сообщение ElisDN »

Ну тут если это экземпляр Object, то конфиг передаётся в конструктор в нужном виде, иначе просто создаётся объект и свойства заполняются вручную через foreach для поддержки простых классов. А если оставить заполнение только через конструктор, то это будет вообще несовместимо со всеми классами без такого конструктора (коих большинство). Так что из двух зол...

А так, чтобы было и независимо от Yii, и зависимо, делают по два пакета: сам независимый компонент и его враппер под фреймворк. Вроде swiftmailer и yii2-swiftmailer. И второй спокойно наследуют от Component.
shkarbatov
Сообщения: 423
Зарегистрирован: 2012.12.10, 14:19
Откуда: Россия

Re: Свойства компонента в его конструкторе

Сообщение shkarbatov »

Это понятно, спасибо.

Не понятно только, почему бы просто не объединить это. То есть и в конструктор и при заполнении свойств через foreach?
shkarbatov
Сообщения: 423
Зарегистрирован: 2012.12.10, 14:19
Откуда: Россия

Re: Свойства компонента в его конструкторе

Сообщение shkarbatov »

Есть у кого-то идеи?
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Свойства компонента в его конструкторе

Сообщение ElisDN »

Тогда надо было бы вручную запускать init() после заполнения атрибутов, как в Yii1.
shkarbatov
Сообщения: 423
Зарегистрирован: 2012.12.10, 14:19
Откуда: Россия

Re: Свойства компонента в его конструкторе

Сообщение shkarbatov »

Почему?
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Свойства компонента в его конструкторе

Сообщение ElisDN »

Потому что сейчас присвоение значений и вызов init() происходят в самом конструкторе:

Код: Выделить всё

class Object implements Configurable
{
    public function __construct($config = [])
    {
        if (!empty($config)) {
            Yii::configure($this, $config);
        }
        $this->init();
    }
} 
shkarbatov
Сообщения: 423
Зарегистрирован: 2012.12.10, 14:19
Откуда: Россия

Re: Свойства компонента в его конструкторе

Сообщение shkarbatov »

Так я говорю, о методе build(), что бы убрать блок if
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Свойства компонента в его конструкторе

Сообщение ElisDN »

Просто Вы хотите ещё раз с foreach после конструктора пройтись, как было разнесено и прокатывало в Yii1, где init() дёргался отдельно:

Код: Выделить всё

abstract class CModule extends CComponent
{
    public function getComponent($id,$createIfNull=true)
    {
        ...
        $component=Yii::createComponent($config);
        $component->init();
        return $this->_components[$id]=$component;
    }
}

class YiiBase
{
    public static function createComponent($config)
    {
        ....
        $object=new $type;
        foreach($config as $key=>$value)
            $object->$key=$value;
        return $object;
    }
} 
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Свойства компонента в его конструкторе

Сообщение ElisDN »

shkarbatov писал(а):Так я говорю, о методе build(), что бы убрать блок if
То есть Вы хотите, чтобы build:
  • 1. Передавал параметры в конструктор
    2. Заполнял параметры ещё раз через foreach
    3. Запускал init()
Я правильно понял?
shkarbatov
Сообщения: 423
Зарегистрирован: 2012.12.10, 14:19
Откуда: Россия

Re: Свойства компонента в его конструкторе

Сообщение shkarbatov »

Я себе представлял это как-то так:

Код: Выделить всё

protected function build($class, $params, $config)
{
    /* @var $reflection ReflectionClass */
    list ($reflection, $dependencies) = $this->getDependencies($class);

    foreach ($params as $index => $param) {
        $dependencies[$index] = $param;
    }

    // set $config as the last parameter (existing one will be overwritten)
    $dependencies[count($dependencies) - 1] = $config;
    $dependencies = $this->resolveDependencies($dependencies, $reflection);
    $object = $reflection->newInstanceArgs($dependencies);

    foreach ($config as $name => $value) {
        $object->$name = $value;
    }

    return $object;
}  
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Свойства компонента в его конструкторе

Сообщение ElisDN »

Тогда нужно будет вынести init из конструктора и всё время дёргать $object->init() самому:

Код: Выделить всё

$object = $reflection->newInstanceArgs($dependencies);
foreach ($config as $name => $value) {
    $object->$name = $value;
}
$object->init();
return $object;
Но в любом случае будут косяки с интерфейсами при скрещиваниии Yii::configure и foreach.

Тогда уж лучше наоборот не делать foreach если это наследник Object:

Код: Выделить всё

$object = $reflection->newInstanceArgs($dependencies);
if (!$object instanceof \yii\base\Object) {
    foreach ($config as $name => $value) {
        $object->$name = $value;
    }
} 
shkarbatov
Сообщения: 423
Зарегистрирован: 2012.12.10, 14:19
Откуда: Россия

Re: Свойства компонента в его конструкторе

Сообщение shkarbatov »

ElisDN писал(а):Но в любом случае будут косяки с интерфейсами при скрещиваниии Yii::configure и foreach.

Тогда уж лучше наоборот не делать foreach если это наследник Object:

Код: Выделить всё

$object = $reflection->newInstanceArgs($dependencies);
if (!$object instanceof \yii\base\Object) {
    foreach ($config as $name => $value) {
        $object->$name = $value;
    }
}
Тут согласен, так-как установка свойств объекта является фишкой фреймворка.

А на счёт init() немного не понятно, зачем заносить в build(), если он и сейчас там не используется?
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Свойства компонента в его конструкторе

Сообщение ElisDN »

Вот init() как раз в конструкторе объектов и используется после установки свойств:

Код: Выделить всё

class Object implements Configurable
{
    public function __construct($config = [])
    {
        if (!empty($config)) {
            Yii::configure($this, $config);
        }
        $this->init();
    }
}
А в последнем моём примере да, можно оставить этот конструктор как есть.
Ответить