Laravel中的反射如何运作?

Kry*_*ska 26 php reflection inversion-of-control laravel

Laravel的反思实际上如何运作?

我尝试调试它以查看Laravel如何在控制器的构造函数或方法中使用反射来解析它们的依赖关系和子依赖关系,然后将其返回给我们.

但我发现它很难,而且看到并且甚至理解50%的情况也很复杂.从一个班级跳到另一个班级,我真的看不到它.我尝试了几次,理解结果很少.

我对这一点和反思印象深刻,而Laravel使用它的方式让我的心脏燃烧 - 它只是美丽的.我希望完全理解 - 整个过程 - 一般而言,一步一步.

击中到最后有路线开始,让我们说,dd($x)其中$x是从方法的参数,是一个TestClass具有另一种依赖性TestClass2应通过构建:$x = new TestClass(new TestClass2());

我认为那些是美丽的机制和架构,理解这是我非常想要的东西.

再说一遍,我的问题是:Laravel的反思实际上是如何运作的?


这不是关于dd男人......让我们说没有dd.正如我之前所说 - 当我们将这个对象从实例中实例化时class method.这不是为之倾倒,它只是从拥有它method injectionreflection.

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

Cy *_*nol 50

Laravel使用PHP的反射API来处理几个组件.其中,开发人员最容易看到控制反转(IoC)依赖注入容器控制器方法注入.

为了更清楚地说明使用反射,这里有一个显着的例行Laravel的简化版本的IoC容器类用来建立通过构造函数注入对象的依赖关系:

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

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

    return $reflector->newInstanceArgs($instances);
}
Run Code Online (Sandbox Code Playgroud)

我们可以看到,这个概念并不难理解.容器使用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);
}
Run Code Online (Sandbox Code Playgroud)

同样,这种改编是精简的,以突出反射的作用,并依赖于我们build()之前显示的功能.本ControllerDispatcher类使用getParameters()PHP的方法ReflectionMethod来确定哪些参数的控制方法需要,然后通过这些循环地发现,代表它可以从容器解析相关参数.然后,它将它找到的每个依赖项拼接回路由参数数组,并将其传递回为路由定义的控制器方法.详情RouteDependencyResolverTrait请见.

如果我们忽略应用程序引导过程,当Laravel将请求映射到路由时,此依赖注入级联通常会启动请求,然后确定将请求传递给哪个控制器.Laravel首先从容器中解析出控制器的一个实例,它构建了任何构造函数注入的依赖项.然后,Laravel找到适当的控制器方法,并根据需要解析参数的任何更多依赖项.

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