Ну вот смотрите, загнал я приложение в контейнер: PHP: $container = new Container(); $application = $container->get(Application::class); // класс Application class Application { public function __construct(Container $container) { var_dump($container); // нет ТАМ никакого Application, голый контейнер :) } } Хорошо, чтобы получить доступ к содержимому контейнера, то идём другим путём: PHP: $container = new Container(); $container->set(Application::class, function(Container $container) { return new Application($container); // как я понимаю на этом месте автовайринг закончился }); $application = $container->get(Application::class); // класс Application class Application { public function __construct(Container $container /* тут если сделать ещё одну инъекцию, то автовайринг не работает */) { var_dump($container); // ТАМ есть Application :) } } Вопрос: как мне теперь в классе Application использовать автовайринг (выше в комментарии класса)? Как я понимаю автовайринг закончился на моменте, когда я мануалом передал в него хоть один параметр, после этого я могу только мануалом туда добавлять? То есть суть такая: как мне в других классах получать содержимое контейнера? Я если добавляю класс в контейнер и передаю контейнер или содержимое по ключу из контейнера в его конструктор, то у меня прекращает работать автовайринг в конструкторе класса, где вручную был добавлен параметр.
Для чего у тебя Application ? --- Добавлено --- Для чего у тебя Application ? --- Добавлено --- Для чего у тебя Application ?
ты уже пол года с Application возишься. --- Добавлено --- Так для чего у тебя Application ? Придет время, ты сможешь ответить на этот вопрос и все проблемы исчезнут
придёт время и я получу ответ на https://php.ru/forum/threads/mozhno-li-vnedrjat-sam-kontejner-pri-avtovajringe.96055/#post-649722 --- Добавлено --- @MouseZver пытаюсь понять: нафиг мне нужен контейнер )))
смотри: PHP: class A { public function __construct($a, B $b, C $c) {} } $a - это какое-то значение из контейнера, хорошо PHP: $container->set(A::class, function() use ($container) { return new A($container->get('a')); }); $container->get(A::class); как видим автовайринг B $b, C $c в конструкторе класса A работает ))) то есть нужно всё ручками добавлять, если добавил хотя бы один параметр и поместил в контейнер А если у меня сотня инъекций с разными типами? --- Добавлено --- как время есть так и вожусь )))
Откуда же мы знаем, как ты его реализовал? Этот автовайринг --- Добавлено --- Я же так понимаю, полный самопис?
Спойлер: Простенький PHP: <?php namespace core; use Closure; use Exception; use ReflectionClass; class Container { private $dependencies; private $results = []; public function __construct($dependencies = []) { $this->dependencies = $dependencies; } public function set($key, $value) { if (array_key_exists($key, $this->results)) { unset($this->results[$key]); } $this->dependencies[$key] = $value; return $this; } public function has($key) { return array_key_exists($key, $this->dependencies) || class_exists($key); } public function get($key) { if (array_key_exists($key, $this->results)) { return $this->results[$key]; } if (!array_key_exists($key, $this->dependencies)) { if (class_exists($key)) { $reflectionClass = new ReflectionClass($key); $args = []; if ($constructor = $reflectionClass->getConstructor()) { foreach ($constructor->getParameters() as $parameter) { if ($class = $parameter->getClass()) { $args[] = $this->get($class->name); } elseif ($parameter->isArray()) { $args[] = []; } elseif (!$parameter->isDefaultValueAvailable()) { throw new Exception("Не указано значение по умолчанию параметра: $parameter->name"); } else { $args[] = $parameter->getDefaultValue(); } /* PHP 8 if (!$parameter->hasType()) { throw new Exception("Не указан тип параметра: $parameter->name"); } if ($parameter->getType()->isBuiltin()) { if (!$parameter->isDefaultValueAvailable()) { throw new Exception("Не указано значение по умолчанию параметра: $parameter->name"); } $args[] = $parameter->getDefaultValue(); } else { $args[] = $this->get($parameter->getType()->getName()); } */ } } return $this->results[$key] = $reflectionClass->newInstanceArgs($args); } throw new Exception("Не найдена зависимость: $key"); } $dependency = $this->dependencies[$key]; if ($dependency instanceof Closure) { $this->results[$key] = $dependency($this); } else { $this->results[$key] = $dependency; } return $this->results[$key]; } }
это ленивая подгрузка анонимкой, анонимка знает о контейнере, там в контейнере в методе get в экземпляр Closure предусмотрена передача контейнера и в анонимку он передаётся явно, если даже явно не передавать, то передать можно в анонимку через use Суть не в этом, а в том, что если я заполню хоть один параметр при ручном добавлении в контейнер, то у меня потом в конструкторе не будет работать автовайринг, там будет только то, что я передал ручным заполнением