当前位置: 首页 > 后端技术 > PHP

Laravel依赖注入源码分析

时间:2023-03-29 20:15:01 PHP

Laravel的controller的构造函数或成员方法可以通过类型约束来使用依赖注入,如:publicfunctionstore(Request$request){//TODO}这里$request参数使用了类型约束。Request是类型约束的类型。它是一个类:IlluminateHttpRequest。本文研究Laravel的依赖注入原理。为什么要定义不需要实例化就可以直接使用Request的方法呢?只是框架帮我们实例化和传递参数而已。让我们来看看这个过程。1、路由定义从源头开始。这样的路由定义在路由定义文件中:Route::resource('/role','Admin\RoleController');这是一个资源类型的路由,Laravel会自动生成增删改查路由条目。本文开头的store方法是一个controller方法,rou??te中定义的action见图:AppHttpControllersAdminRoleController@storeroute方法分析根据route定义找到controller和method,并实现了这个过程在调度方法中。(文件:vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php)publicfunctiondispatch(Route$route,$controller,$method){$parameters=$this->resolveClassMethodDependencies($route->parametersWithoutNulls(),$控制器,$方法);如果(method_exists($controller,'callAction')){return$controller->callAction($method,$parameters);}return$controller->{$method}(...array_values($parameters));}这里是resolveClassMethodDependencies方法,“顾名思义”这个方法是用来从类方法中获取依赖对象的:protectedfunctionresolveClassMethodDependencies(array$参数,$instance,$method){if(!method_exists($instance,$method)){return$parameters;}return$this->resolveMethodDependencies($parameters,newReflectionMethod($instance,$method));}这里重点是使用PHP的反射,注意ReflectionMethod方法,它获取类的方法参数列表,可以知道参数的类型约束,参数名等等。这里的$instance参数是RoleController控制器类,$method参数是方法名strore。2.获取依赖对象的例子从方法的参数中获取依赖对象的约束类型,然后实例化依赖对象。受保护的函数transformDependency(ReflectionParameter$parameter,$parameters){$class=$parameter->getClass();//如果参数有类型提示类,我们将检查它是否已经在//参数列表中。如果是,我们将跳过它,因为它可能是一个模型//绑定,我们不想弄乱那些;否则,我们在这里解决。如果($class&&!$this->alreadyInParameters($class->name,$parameters)){返回$parameter->isDefaultValueAvailable()?$parameter->getDefaultValue():$this->container->make($class->name);}}从容器中根据类名获取对象,绑定对象实例的过程首先定义在服务提供者中。然后将实例化的对象传入store方法,就可以使用依赖对象了。3、关于PHP反射,举个使用ReflectionMethod的例子。演示类{private$request;publicfunctionstore(Request$request){}}打印出newReflectionMethod(Demo::class,'store')的内容如图:可以得到这个方法的参数列表,参数的约束类型,例如typeHint、IlluminateHttpRequest。根据类名,可以从容器中获取到服务提供者一开始绑定的实例。(原文地址:https://blog.tanteng.me/2018/...)