Задать вопрос
@HP_KDE_neon

Автовайрить контейнером самого себя — это «законно»?

Container::get

public function get(string $key): mixed
{
    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);

            $constructor = $reflectionClass->getConstructor();

            if (is_null($constructor)) {
                $this->results[$key] = $reflectionClass->newInstanceWithoutConstructor();

                return $this->results[$key];
            }

            $parameters = $constructor->getParameters();

            if (empty($parameters)) {
                $this->results[$key] = $reflectionClass->newInstance();

                return $this->results[$key];
            }

            $args = [];

            foreach ($parameters as $parameter) {

                if (!$parameter->hasType()) {
                    throw new Exception("Не указан тип параметра: $parameter->name");
                }

                $type = $parameter->getType();

                if ($type->isBuiltin()) {

                    if (!$parameter->isDefaultValueAvailable()) {
                        throw new Exception("Не указано значение по умолчанию параметра: $parameter->name");
                    }

                    $args[] = $parameter->getDefaultValue();
                } else {
                    $class = $type->getName();

                    $args[] = $this instanceof $class ? $this : $this->get($class); // есть возможность автовайрить контейнер
                    // $args[] = $this->get($type->getName()); // старая версия - нет возможности автовайрить контейнер
                }
            }

            $this->results[$key] = $reflectionClass->newInstanceArgs($args);

            return $this->results[$key];
        }

        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];
}



Суть вопроса в цикле после else - прописана возможность автовайрить контейнер.

А каково мнение сообщества о таком применении?

Есть моменты, где требуется внедрение самого контейнера и приходится заранее собирать зависимости в контейнер с персональным внедрением контейнера, если контейнер не внедряется, то такие зависимости не собираются отдельно, так как автовайрятся, поэтому вопрос такой.
  • Вопрос задан
  • 135 просмотров
Подписаться 1 Простой Комментировать
Решения вопроса 1
В Symfony и Laravel контейнер доступен в виде зависимости. Но, например, в Symfony оооочень сильно отговаривают от любого использования контейнера в клиентском коде, потому что код мгновенно начинает источать запах:

1. Антипаттерн Service Locator: Внедрение контейнера может привести к скрытым зависимостям

2. Нарушение принципа инверсии зависимостей: Классы становятся зависимыми от контейнера

3. Усложнение тестирования: Нужно мокать весь контейнер

Но иногда, когда, например, динамическое внедрение зависимостей в каком-то конкретном месте вам необходимо, как воздух, то контейнер может помочь.

Поэтому тут надо просто использовать разумный подход:

1. Никогда не внедряем в свой код контейнер в виде зависимости в качестве первого решения проблемы.
2. Если проблема всё же не позволяет обойтись любыми другими средствами, то только тогда внедряем контейнер и очень хорошо документируем причину такого выбора и весь код класса. Потому что это обычно что-то хитрое, что забудется через месяц, и потом будет тяжко возвращаться к этому коду.

Итого: пусть будет на очень крайний случай
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы