在 Laravel 的控制器的构造方法或者成员方法,都可以通过类型约束的方式使用依赖注入,如:
public function store(Request $request) { //TODO }
这里 $request 参数就使用了类型约束,Request 是类型约束的类型,它是一个类:IlluminateHttpRequest.
本文研究 Laravel 的依赖注入原理,为什么这样定义不需要实例化就可以直接使用 Request 的方法呢?只是框架帮我们实例化并传参了,我们看看这个过程。
1.路由定义从源头开始看起,在路由定义文件中定义了这么一个路由:
Route::resource("/role", "AdminRoleController");
这是一个资源型的路由,Laravel 会自动生成增删改查的路由入口。
本文开头的 store 方法就是一个控制器的方法,图中可见路由定义的 Action 也是:AppHttpControllersAdminRoleController@store
根据路由定义找到控制器和方法,这个过程在 dispatch 方法中实现。
(文件:vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php)
public function dispatch(Route $route, $controller, $method) { $parameters = $this->resolveClassMethodDependencies( $route->parametersWithoutNulls(), $controller, $method ); if (method_exists($controller, "callAction")) { return $controller->callAction($method, $parameters); } return $controller->{$method}(...array_values($parameters)); }
这里 resolveClassMethodDependencies 方法,“顾名思义”这个方法的作用是从类的方法中获取依赖对象:
protected function resolveClassMethodDependencies(array $parameters, $instance, $method) { if (! method_exists($instance, $method)) { return $parameters; } return $this->resolveMethodDependencies( $parameters, new ReflectionMethod($instance, $method) ); }
这里重点就是用到了 PHP 的反射,注意 RelectionMethod 方法,它获取到类的方法参数列表,可以知道参数的类型约束,参数名称等等。
这里的 $instance 参数就是 RoleController 控制器类,$method 参数就是方法名称 strore.
2.获取依赖对象的示例从方法的参数中获取了依赖对象的约束类型,就可以实例化这个依赖的对象。
protected function transformDependency(ReflectionParameter $parameter, $parameters) { $class = $parameter->getClass(); // If the parameter has a type-hinted class, we will check to see if it is already in // the list of parameters. If it is we will just skip it as it is probably a model // binding and we do not want to mess with those; otherwise, we resolve it here. if ($class && ! $this->alreadyInParameters($class->name, $parameters)) { return $parameter->isDefaultValueAvailable() ? $parameter->getDefaultValue() : $this->container->make($class->name); } }
根据类名从容器中获取对象,这个绑定对象实例的过程在服务提供者中先定义和了。
然后把实例化的对象传入到 store 方法中,就可以使用依赖的对象了。
3.关于 PHP 反射举个使用 ReflectionMethod 的例子。
class Demo { private $request; public function store(Request $request) { } }
打印出 new ReflectionMethod(Demo::class, ‘store’) 的内容如图:
可以得出这个方法的参数列表,参数的约束类型,如 typeHint,IlluminateHttpRequest.
根据类名可以从容器中获取一开始通过服务提供者绑定的实例。
(原文地址:https://blog.tanteng.me/2018/...)
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/28121.html
摘要:划下重点,服务容器是用于管理类的依赖和执行依赖注入的工具。类的实例化及其依赖的注入,完全由服务容器自动的去完成。 本文首发于 深入剖析 Laravel 服务容器,转载请注明出处。喜欢的朋友不要吝啬你们的赞同,谢谢。 之前在 深度挖掘 Laravel 生命周期 一文中,我们有去探究 Laravel 究竟是如何接收 HTTP 请求,又是如何生成响应并最终呈现给用户的工作原理。 本章将带领大...
摘要:用匿名函数的好处在于,这个服务绑定到容器以后,并不会立即产生服务最终的对象,只有在这个服务解析的时候,匿名函数才会执行,此时才会产生这个服务对应的服务实例。 前言 老实说,第一次老大让我看laravel框架手册的那天早上,我是很绝望的,因为真的没接触过,对我这种渣渣来说,laravel的入门门槛确实有点高了,但还是得硬着头皮看下去(虽然到现在我还有很多没看懂,也没用过)。 后面慢...
摘要:而函数作用是加载延迟服务,与容器解析关系不大,我们放在以后再说。在构造之前,服务容器会先把放入中,继而再去解析。利用服务容器解析依赖的参数。 make解析 首先欢迎关注我的博客: www.leoyang90.cn 服务容器对对象的自动解析是服务容器的核心功能,make 函数、build 函数是实例化对象重要的核心,先大致看一下代码: public function make($abst...
摘要:依赖注入依赖注入一词是由提出的术语,它是将组件注入到应用程序中的一种行为。就像说的依赖注入是敏捷架构中关键元素。类依赖于,所以我们的代码可能是这样的创建一个这是一种经典的方法,让我们从使用构造函数注入开始。 showImg(https://segmentfault.com/img/remote/1460000018806800); 文章转自:https://learnku.com/la...
摘要:的核心概念包括服务容器服务提供者门面契约。所有服务提供者都需要继承类。可以为服务提供者的方法设置类型提示。方法将在所有其他服务提供者均已注册之后调用。同样会整理成思维导图的形式以方便记忆与回顾。 showImg(https://segmentfault.com/img/remote/1460000010771201); Laravel 的核心概念包括:服务容器、服务提供者、门面(Fac...
阅读 3710·2021-09-09 09:33
阅读 2988·2019-08-30 15:56
阅读 2994·2019-08-30 15:56
阅读 3282·2019-08-30 15:55
阅读 481·2019-08-30 15:53
阅读 2158·2019-08-30 15:52
阅读 637·2019-08-28 18:16
阅读 2320·2019-08-26 13:51