gpt4 book ai didi

php - Laravel 中的反射是如何工作的?

转载 作者:IT王子 更新时间:2023-10-29 01:24:21 26 4
gpt4 key购买 nike

Laravel 中的反射实际上是如何工作的?

我尝试调试它以了解 Laravel 如何在 Controller 的构造函数或方法中使用反射来解决它们的依赖关系和子依赖关系,然后将其返回给我们。

但是我觉得很难,看到甚至理解50%都非常复杂。从一个类(class)跳到另一个类(class),实在看不下去。我尝试了几次调试,但理解的结果很低。

我对此和反射(reflection)印象深刻,Laravel 使用它的方式让我的心在燃烧——它太美了。我希望全面地、逐步地​​全面了解整个过程。

从找到路径到最后,比方说,dd($x),其中 $x 来自方法参数,是一个 TestClass 具有 TestClass2 的另一个依赖项,应该通过以下方式构建:$x = new TestClass(new TestClass2());

我认为这些都是美丽的机制和架构,理解这一点是我非常想要的。

那么,我的问题是:Laravel 中的反射实际上是如何工作的?


这与 dd 家伙无关...假设没有 dd。正如我之前所说 - 当我们从 class 方法实例化这个对象时。这不是关于倾倒它,它只是关于通过反射方法注入(inject)中获得它。

dd 只是一个例子。它甚至可以是 die(var_dump()); 并且它会起作用

最佳答案

Laravel 使用 PHP 的 reflection API对于几个组件。其中,控制反转 (IoC) dependency injection container Controller method injection 对开发人员来说最为明显。

为了更清楚地说明反射的使用,这是 Laravel 的 IoC container class 例程的戏剧性简化版本。用于通过构造函数注入(inject)建立对象的依赖关系:

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() 最终实例化原始类并将依赖项作为参数传递给构造函数。

Controller 方法注入(inject)使用与上述相同的容器功能来解析声明为方法参数的依赖项实例,但是需要一些额外的逻辑来将类依赖项与路由参数分开:

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的方法确定 Controller 方法需要哪些参数,然后遍历这些参数以查找表示它可以从容器中解析的依赖项的参数。然后,它将找到的每个依赖项拼接回路由参数数组,然后传递回为路由定义的 Controller 方法。见 RouteDependencyResolverTrait了解详情。

如果我们忽略应用程序的引导过程,这种依赖注入(inject)级联通常会在 Laravel 将请求映射到路由时为请求启动,然后确定将请求传递给哪个 Controller 。 Laravel 首先从容器中解析 Controller 的一个实例,该实例构建出任何构造函数注入(inject)的依赖项。然后,Laravel 找到合适的 Controller 方法,并根据需要解析参数的更多依赖关系。

如此处所示,Laravel 使用相对简单的技术通过反射来实现这些工具。但是,与此答案中显示的示例不同,该框架添加了许多额外的代码,以使它们像现在一样健壮和灵活。

关于php - Laravel 中的反射是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47200527/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com