php - property - ¿Cómo funciona Reflection in Laravel?
reflection php example (1)
Laravel utiliza la API de reflexión de PHP para varios componentes. De estos, el contenedor de inyección de dependencia de inverson-of-control (IoC) y el método de inyección del controlador son más visibles para los desarrolladores.
Para ilustrar más claramente el uso de la reflexión, aquí hay una versión dramáticamente simplificada de la rutina que utiliza la clase de contenedor IoC de Laravel para construir las dependencias de un objeto a través de la inyección del constructor:
function build($className)
{
$reflector = new ReflectionClass($className);
$constructor = $reflector->getConstructor();
foreach ($constructor->getParameters() as $dependency) {
$instances[] = build($dependency->getClass()->name);
}
return $reflector->newInstanceArgs($instances);
}
Como podemos ver, el concepto no es demasiado difícil de entender. El contenedor utiliza ReflectionClass
de PHP para encontrar los nombres de las clases en el constructor de un objeto, y luego recorre cada uno de estos nombres de forma recursiva para crear instancias de cada objeto en el árbol de dependencia. Con estas instancias, build()
finalmente build()
instancia de la clase original y pasa las dependencias como argumentos al constructor.
La inyección del método del controlador utiliza la misma funcionalidad de contenedor que se muestra arriba para resolver las instancias de las dependencias declaradas como parámetros del método, pero se necesita un poco de lógica adicional para separar las dependencias de clase de los parámetros de ruta:
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);
}
Una vez más, esta adaptación se ha simplificado para resaltar el papel que desempeña la reflexión y se basa en la función de build()
que se muestra anteriormente. La clase ControllerDispatcher
usa el método getParameters()
del ReflectionMethod
de PHP para determinar qué parámetros espera un método de controlador, y luego realiza un bucle a través de estos para encontrar parámetros que representan dependencias que puede resolver desde el contenedor. Luego, empalma cada dependencia que encuentra de nuevo en la matriz de parámetros de ruta que pasa al método del controlador definido para la ruta. Ver RouteDependencyResolverTrait
para más detalles.
Si ignoramos el proceso de arranque de la aplicación, esta cascada de inyección de dependencias normalmente se inicia para una solicitud cuando Laravel asigna una solicitud a una ruta, y luego determina a qué controlador pasar la solicitud. Laravel primero resuelve una instancia del controlador desde el contenedor, que construye las dependencias inyectadas por el constructor. Luego, Laravel encuentra el método de controlador apropiado y resuelve las dependencias más para los argumentos según sea necesario.
Como se muestra aquí, Laravel usa técnicas relativamente simples para implementar estas herramientas usando la reflexión. Sin embargo, a diferencia de los ejemplos que se muestran en esta respuesta, el marco agrega una gran cantidad de código adicional para que sean tan robustos y flexibles como lo son hoy.
¿Cómo funciona realmente la reflexión en Laravel?
Traté de depurarlo para ver cómo Laravel utiliza la reflexión en el constructor o los métodos de un controlador para resolver sus dependencias y subdependencias y luego devolvérnoslo.
Pero me resultó difícil, y es muy complicado ver e incluso comprender el 50% de. Saltando de clase en clase, realmente no puedo verlo. Lo intenté varias veces depurándolo con bajos resultados de comprensión.
Estoy muy impresionado por esto y por la reflexión, y la forma en que Laravel lo usa hace que mi corazón arda, es simplemente hermoso. Y deseo entender completamente eso, todo el proceso, en general, y paso a paso.
Comenzando desde tomar la ruta hasta finalmente tener, digamos, dd($x)
, donde $x
es de un argumento de método y es un TestClass
que tiene otra dependencia de TestClass2
que debe construirse a través de: $x = new TestClass(new TestClass2());
Creo que esos son hermosos mecánicos y arquitectura, y entender esto es algo que quiero tanto.
Entonces, una vez más, mi pregunta es: ¿cómo funciona realmente la reflexión en Laravel?
No se trata de chicos dd
... Digamos sin dd
. Como dije anteriormente, cuando tenemos este objeto instanciado desde el class method
. No se trata de deshacerse de él, solo se trata de method injection
mediante la method injection
.
El dd
era solo un ejemplo. Incluso puede ser die(var_dump());
y funcionará