php+laravel依赖注入知识点总结


Posted in PHP onNovember 04, 2019

laravel容器包含控制反转和依赖注入,使用起来就是,先把对象bind好,需要时可以直接使用make来取就好。

通常我们的调用如下。

$config = $container->make('config');
$connection = new Connection($this->config);

比较好理解,这样的好处就是不用直接 new 一个实例了,方法传值没啥改变,还可以多处共享此实例。

但这跟依赖注入有什么关系,真正的依赖注入是不需给方法传递任何参数值,只需要指明方法参数类型,代码自动查找关系依赖自动注入。

这个特性在 laravel 的 Controller、Job 等处可以体现,如下:

class TestController extends Controller
{
public function anyConsole(Request $request, Auth $input)
{
//todo
}
}

我们来看下他是怎么实现自动依赖注入的:

由 index.php 调用 Kernel ,经过多层 Kernel 管道调用,再到 Router ,经过多层中间件管道调用。最终定位到

Illuminate/Routing/Route.php 第124行。

public function run(Request $request)
{
$this->container = $this->container ?: new Container;
try {
if (! is_string($this->action['uses'])) {
return $this->runCallable($request);
}

if ($this->customDispatcherIsBound()) {
return $this->runWithCustomDispatcher($request);
}

return $this->runController($request);
} catch (HttpResponseException $e) {
return $e->getResponse();
}
}

判断 $this->action['uses'](格式行如:\App\Http\Controller\Datacenter\RealTimeController@anyConsole)是否字符串, $this->customDispatcherIsBound判断是否绑定了用户自定义路由。然后跳转到 $this->runController($request)。

protected function runController(Request $request)
{
list($class, $method) = explode('@', $this->action['uses']);

$parameters = $this->resolveClassMethodDependencies(
$this->parametersWithoutNulls(), $class, $method
);

if (! method_exists($instance = $this->container->make($class), $method)) {
throw new NotFoundHttpException;
}

return call_user_func_array([$instance, $method], $parameters);
}

$this->resolveClassMethodDependencies 这个方法一看名字就知道是我们要找的方法。$this->parametersWithoutNulls()是过滤空字符,$class、$method分别行如:\App\Http\Controller\Datacenter\RealTimeController 与 anyConsole。

protected function resolveClassMethodDependencies(array $parameters, $instance, $method)
{
if (! method_exists($instance, $method)) {
return $parameters;
}

return $this->resolveMethodDependencies(
$parameters, new ReflectionMethod($instance, $method)
);
}

new ReflectionMethod($instance, $method) 是拿到类方法的反射对象,参见文档:http://www.php.net/manual/zh/class.reflectionmethod.php

下面跳转到Illuminate/Routing/RouteDependencyResolverTrait.php 第54行。

public function resolveMethodDependencies(array $parameters, ReflectionFunctionAbstract $reflector)
{
$originalParameters = $parameters;

foreach ($reflector->getParameters() as $key => $parameter) {
$instance = $this->transformDependency(
$parameter, $parameters, $originalParameters
);

if (! is_null($instance)) {
$this->spliceIntoParameters($parameters, $key, $instance);
}
}

return $parameters;
}

通过反射类方法得到类参数数组,然后遍历传递给 $this->transformDependency 方法。如果实例获取不到则调用 $this->spliceIntoParameters 清楚该参数。

protected function transformDependency(ReflectionParameter $parameter, $parameters, $originalParameters)
{
$class = $parameter->getClass();
if ($class && ! $this->alreadyInParameters($class->name, $parameters)) {
return $this->container->make($class->name);
}
}

终于看到了容器的影子,没错最终对象还是通过容器的 make 方法取出来的。至此参数就构造好了,然后最终会被 runController 方法的 call_user_func_array 回调。

总结:

1. 依赖注入原理其实就是利用类方法反射,取得参数类型,然后利用容器构造好实例。然后再使用回调函数调起。

2. 注入对象构造函数不能有参数。否则会报错。Missing argument 1

3. 依赖注入故然好,但它必须要由 Router 类调起,否则直接用 new方式是无法实现注入的。所以这就为什么只有 Controller 、Job 类才能用这个特性了。

以上就是关于php+laravel依赖注入的全部知识点内容,感谢大家的学习和对三水点靠木的支持。

PHP 相关文章推荐
用PHP伪造referer突破网盘禁止外连的代码
Jun 15 PHP
PHP 执行系统外部命令 system() exec() passthru()
Aug 11 PHP
php cli 方式 在crotab中运行解决
Feb 08 PHP
PHP下打开URL地址的几种方法小结
May 16 PHP
PHP curl 获取响应的状态码的方法
Jan 13 PHP
php实现根据字符串生成对应数组的方法
Sep 22 PHP
php使用GD创建保持宽高比缩略图的方法
Apr 17 PHP
PHP简单读取PDF页数的实现方法
Jul 21 PHP
PHP图片裁剪与缩放示例(无损裁剪图片)
Feb 08 PHP
Laravel网站打开速度优化的方法汇总
Jul 16 PHP
PHP异常处理定义与使用方法分析
Jul 25 PHP
PHP自定义函数实现数组比较功能示例
Oct 19 PHP
PHP保存Base64图片base64_decode的问题整理
Nov 04 #PHP
详解laravel passport OAuth2.0的4种模式
Nov 04 #PHP
laravel返回统一格式错误码问题
Nov 04 #PHP
php 中self,this的区别和操作方法实例分析
Nov 04 #PHP
PHP 文件写入和读取操作实例详解【必看篇】
Nov 04 #PHP
PHP连接MySQL数据库的三种方式实例分析【mysql、mysqli、pdo】
Nov 04 #PHP
php ZipArchive实现多文件打包下载实例
Oct 31 #PHP
You might like
dedecms中显示数字验证码的修改方法
2007/03/21 PHP
php数组对百万数据进行排除重复数据的实现代码
2010/06/08 PHP
php查询whois信息的方法
2015/06/08 PHP
Laravel 5.3 学习笔记之 错误&日志
2016/08/28 PHP
PHP 文件上传后端处理实用技巧方法
2017/01/06 PHP
php实现获取农历(阴历)、节日、节气的类与用法示例
2017/11/20 PHP
javaScript让文本框内的最后一个文字的后面获得焦点实现代码
2013/01/06 Javascript
jQuery 三击事件实现代码
2013/09/11 Javascript
JavaScript继承基础讲解(原型链、借用构造函数、混合模式、原型式继承、寄生式继承、寄生组合式继承)
2014/08/16 Javascript
JQuery简单实现锚点链接的平滑滚动
2015/05/03 Javascript
jQuery获取file控件中图片的宽高与大小
2016/08/04 Javascript
AngularJS过滤器详解及示例代码
2016/08/16 Javascript
学习vue.js条件渲染
2016/12/03 Javascript
vue+axios新手实践实现登陆的示例代码
2018/06/06 Javascript
JavaScript作用域链实例详解
2019/01/21 Javascript
微信小程序实现文件、图片上传功能
2020/08/18 Javascript
javascript 构建模块化开发过程解析
2019/09/11 Javascript
vue-quill-editor的使用及个性化定制操作
2020/08/04 Javascript
[01:00:35]2018DOTA2亚洲邀请赛3月30日B组 EffcetVSMineski
2018/03/31 DOTA
python 将数据保存为excel的xls格式(实例讲解)
2018/05/03 Python
详解Python 解压缩文件
2019/04/09 Python
Python之Class&Object用法详解
2019/12/25 Python
python 解决pycharm运行py文件只有unittest选项的问题
2020/09/01 Python
西班牙太阳镜品牌:Hawkers
2018/03/11 全球购物
在校生汽车维修实习自我鉴定
2013/09/19 职场文书
秘书专业自荐信范文
2013/12/26 职场文书
单位刻章介绍信范文
2014/01/11 职场文书
2014年五四青年节活动策划书
2014/04/22 职场文书
效能风暴心得体会
2014/09/04 职场文书
2015年员工试用期工作总结
2014/12/12 职场文书
2014年生产管理工作总结
2014/12/23 职场文书
招标保密承诺书
2015/01/20 职场文书
幼儿园中班教师个人总结
2015/02/05 职场文书
考博导师推荐信范文
2015/03/27 职场文书
2015年征兵工作总结
2015/07/23 职场文书
Matplotlib绘制条形图的方法你知道吗
2022/03/21 Python