Конструктор виджетов

Обсуждаем разработку фреймворка: дизайн компонентов, API, пакеты

Какой способ вам нравится больше и почему?

Зависимость через конструктор
4
67%
Зависимость через сеттер
2
33%
 
Всего голосов: 6

Аватара пользователя
maleks
Сообщения: 1858
Зарегистрирован: 2012.12.26, 12:56

Re: Конструктор виджетов

Сообщение maleks »

roxblnfk, ясно, спасибо за подробный ответ.
Yii2 universal module sceleton - for basic and advanced templates

yiiliveext
Сообщения: 910
Зарегистрирован: 2019.08.13, 01:49

Re: Конструктор виджетов

Сообщение yiiliveext »

samdark писал(а):
2020.01.24, 14:47
По задумке должен подменять. Я не вижу сходу почему это не случается. Если это так, то это баг factory. Если знаете как поправить, расскажите.
Я думаю было бы логично, если бы фабрика в методе create использовала бы композитный контейнер из контейнера полученного через конструктор и самой фабрики(как контейнера), естественно с приоритетом фабрики(как контейнера) (не помню что там за чем для этого добавлять в композитном контейнере). Тогда при создании фабрики мы можем установить/переопределить локальные зависимости для объектов, создаваемых этой фабрикой, не изменяя при этом глобальный/внедренный контейнер, но его зависимости по-прежнему будут доступны. По факту композитный контейнер должен создаваться в конструкторе фабрики и записываться в $this->container.
У вас же, если установлен контейнер в конструкторе фабрики, то берется он, если нет - то используется фабрика как контейнер
Вот в ArrayBuilder

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

private function resolveDependencies(ContainerInterface $container, array $dependencies): array
    {
        $container = $container->container ?? $container;
       //...
    }
То есть, если я сейчас видоизменю неработающий пример кода (поставлю контейнеру null) на

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

$provider = new \Yiisoft\EventDispatcher\Provider\Provider();
    $dispatcher = new \Yiisoft\EventDispatcher\Dispatcher($provider);
    WidgetFactory::initialize(null, [
        EventDispatcherInterface::class => $dispatcher
    ]);

то все отлично заработает, потому как теперь как контейнер используется сама фабрика с нашим определением своего диспетчера.
Если есть какие-то причины/кейсы использования фабрики как исключительно локального контейнера, то объясните, если вас не затруднит.

yiiliveext
Сообщения: 910
Зарегистрирован: 2019.08.13, 01:49

Re: Конструктор виджетов

Сообщение yiiliveext »

Решение проблемы.
В классе Yiisoft\Factory\Factory меняем три метода на

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

public function __construct(ContainerInterface $container = null, array $definitions = [])
    {
        $compositeContainer = new CompositeContainer();
        $compositeContainer->attach($container);
        $compositeContainer->attach($this);
        $this->container = $compositeContainer;
        $this->setMultiple($definitions);
    }

public function create($config, array $params = [])
    {
        return Normalizer::normalize($config)->resolve($this->container, $params);
    }

public function get($id, array $params = [])
    {
        return $this->getDefinition($id)->resolve($this->container, $params);
    }

В классе Yiisoft\Factory\Definitions\ArrayBuilder удаляем строку

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

    $container = $container->container ?? $container;
И в Yiisoft\Di\CompositeContainer еще исправьте, замените на это (нужно при формировании списка контейнеров из внешнего источника, когда может прийти null, это как раз наш случай)

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

public function attach(?ContainerInterface $container): void
    {
        if (isset($container)) {
            array_unshift($this->containers, $container);
        }
    }
Добил исправления, тесты все проходят. Выше не все исправлено, сделаю PR.

Ответить