Решил воспользоваться внедрением зависимости в экшн, но оказалось что эту возможность выпилили.
Причина выпиливания, лично мне, кажется вполне обоснованной (устранить микс источника аргументов в экшене).
Но и оппонентов понять можно: разным экшенам нужны разные зависимости, а при внедрении в конструктор он создаются все вместе.
Предлагаю рассмотреть ввод понятния отложенного создания зависимости.
То есть внедряется не сама зависимость, а, грубо говоря, ее геттер, который создает инстанс зависимости когда он вызывается, или берет уже созданный (если это синглтон). Такой объект будет крайне легковесным.
Наверное, документация Dagger чуше опишет что я имею виду http://google.github.io/dagger/users-gu ... injections (раздел Lazy injections)
Отложенное создание DI зависимостей
Отложенное создание DI зависимостей
Последний раз редактировалось mitaichik 2016.11.16, 00:32, всего редактировалось 1 раз.
Re: Отложенное создание DI зависимостей
А какие проблемы с созданием нескольких сервисов сразу?
Re: Отложенное создание DI зависимостей
У меня проблем нет, но это решение для тех, кто не хочет создавать неиспользуемые сервисы, например, ввиду их тяжелости создания (я имею ввиду долгой инициализации).ElisDN писал(а):А какие проблемы с созданием нескольких сервисов сразу?
Re: Отложенное создание DI зависимостей
Им советую не путать причину со следствием и не делать такие сервисы с тяжёлой инициализацией в конструкторе.mitaichik писал(а):решение для тех, кто не хочет создавать неиспользуемые сервисы, например, ввиду их тяжелости создания (я имею ввиду долгой инициализации).
А так если сервисов много, то пусть либо дёргают Yii::createObject или Yii::$container->get напрямую в экшене (вместо инъекции в конструктор контроллера), либо разбивают контроллеры на более узкоспециализированные.
А ленивую загрузку можно сделать и самому:
Код: Выделить всё
$container->set('my\Service', function ($container) {
return Lazy::create('my\Service', $container);
});
Код: Выделить всё
class Lazy
{
public static function create($class, Container $container, $arguments = null)
{
$methods = (new ReflectionClass($class))->getMethods(ReflectionClass::IS_PUBLIC);
$methodsCode = implode(PHP_EOL, array_map(function (Method $method) {
return 'public function ' . $method->getName() . '( '. ... . ') { return $this->getOriginalObject()->' . $method->getName() . '(' . ... . '); }';
}, array_filter($methods, function (Method $method) {
return !$method->isStatic();
})));
$proxyClass = $class . 'Proxy' . $rand;
eval("class $proxyClass extends $class {
use ProxyTrait;
$methodsCode
}");
return new $proxyClass($class, $container, $arguments);
}
}
Код: Выделить всё
trait ProxyTrait
{
private $_class;
private $_container;
private $_arguments;
private $_object;
public function __construct($class, $container, $arguments)
{
$this->_class = $class;
$this->_container = $container;
$this->_arguments = $arguments;
}
protected getOriginalObject()
{
if ($this->_object === null) {
$arguments = is_array($this->_arguments) ? $this->_arguments : call_user_func($this->_arguments, $this->_container);
$this->_object = (new ReflectionClass($this->_class))->newInstanceArgs($arguments);
}
return $this->_object;
}
}