Как работает отражение в Laravel?


Как на самом деле работает отражение в Laravel?

Я попытался отладить его, чтобы увидеть, как Laravel использует отражение в конструкторе или методах контроллера для разрешения их зависимостей и зависимостей, а затем и вернуть его нам.

Но мне было трудно, и это очень сложно увидеть и даже понять на 50%. Прыгая из класса в класс, я на самом деле этого не вижу. Я несколько раз пытался отладить его с низкими результатами понимания.

Я очень впечатленный этим и размышлениями, и то, как Ларавель использует это, заставляет мое сердце гореть - это просто прекрасно. И я хочу полностью понять это - весь процесс - в целом и шаг за шагом.

Начиная с прохождения маршрута и заканчивая, скажем, dd($x), где $x - это аргумент метода и TestClass, у которого есть другая зависимость TestClass2, которая должна быть построена через: $x = new TestClass(new TestClass2());

Я думаю, что это прекрасная механика и архитектура, и понимание этого это то, чего я так сильно хочу.

Итак, снова мой вопрос: как на самом деле работает отражение в Laravel?


Дело не в dd парнях... Скажем, без dd. Как я уже говорил ранее - когда у нас есть экземпляр этого объекта из class method. Речь идет не о том, чтобы выбросить его, а просто о том, чтобы получить его от method injection reflection.

dd был всего лишь примером. Это может быть даже die(var_dump());, и это будет работать

Author: Cy Rossignol, 2017-11-09

1 answers

Laravel использует PHPAPI отражения для нескольких компонентов. Из них инверсионный контроль (МОК) контейнер для инъекции зависимостей и контроллер впрыск метода наиболее заметны для разработчиков.

Чтобы более четко проиллюстрировать использование отражения, вот значительно упрощенная версия процедуры контейнерного класса IoC Laravel, используемого для создания зависимостей объекта посредством инъекция конструктора:

function build($className) 
{
    $reflector = new ReflectionClass($className);
    $constructor = $reflector->getConstructor();

    foreach ($constructor->getParameters() as $dependency) {
        $instances[] = build($dependency->getClass()->name);
    }

    return $reflector->newInstanceArgs($instances);
}

Как мы видим, эту концепцию не так уж сложно понять. Контейнер использует PHP ReflectionClass чтобы найти имена классов в конструкторе объекта, а затем рекурсивно перебирать каждое из этих имен для создания экземпляров каждого объекта в дереве зависимостей. С помощью этих экземпляров build(), наконец, создает экземпляр исходного класса и передает зависимости в качестве аргументов конструктору.

Способ управления внедрение использует ту же функциональность контейнера, показанную выше, для разрешения экземпляров зависимостей, объявленных в качестве параметров метода, но для отделения зависимостей класса от параметров маршрута требуется немного дополнительной логики:

function dispatch(Route $route, Controller $controller, $methodName) 
{
    $routeParameters = $route->parametersWithoutNulls();
    $method = new ReflectionMethod($controller, $methodName);

    foreach ($method->getParameters() as $index => $parameter) {
        $class = $parameter->getClass();

        if ($class !== null) {
            $instance = build($class->name);
            array_splice($routeParameters, $index, 0, [ $instance ]);
        }
    }

    $controller->callAction($methodName, $routeParameters);
}

Опять же, эта адаптация уменьшена, чтобы подчеркнуть роль, которую играет отражение, и опирается на нашу функцию build(), показанную ранее. Тот ControllerDispatcher класс использует getParameters() метод PHP-х ReflectionMethod чтобы определить, какие параметры a метод контроллера ожидает, а затем перебирает их, чтобы найти параметры, представляющие зависимости, которые он может разрешить из контейнера. Затем он объединяет каждую найденную зависимость обратно в массив параметров маршрута, которые он передает обратно методу контроллера, определенному для маршрута. Видишь RouteDependencyResolverTrait для получения более подробной информации.

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

Как показано здесь, Laravel использует относительно простые методы для реализации этих инструментов с использованием отражения. Однако, в отличие от примеров, показанных в этом ответе, структура добавляет много дополнительного кода, чтобы сделать их такими же надежными и гибкими, как сегодня.

 38
Author: Cy Rossignol, 2018-01-29 20:02:44