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 相关文章推荐
使用数据库保存session的方法
Oct 09 PHP
PHP新手上路(十二)
Oct 09 PHP
php加水印的代码(支持半透明透明打水印,支持png透明背景)
Jan 17 PHP
基于PHP array数组的教程详解
Jun 05 PHP
php生成图形验证码几种方法小结
Aug 15 PHP
IIS下PHP的三种配置方式对比
Nov 20 PHP
简要剖析PHP的Yii框架的组件化机制的基本知识
Mar 17 PHP
php实现XML和数组的相互转化功能示例
Feb 08 PHP
php数据结构之顺序链表与链式线性表示例
Jan 22 PHP
PHP实现的CURL非阻塞调用类
Jul 26 PHP
PHP获取星期几的常用方法小结
Dec 18 PHP
浅谈PHP中的Trait使用方法
Mar 22 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
Apache2 httpd.conf 中文版
2006/12/06 PHP
PHP的SQL注入过程分析
2012/01/06 PHP
PHP字符串长度计算 - strlen()函数使用介绍
2013/10/15 PHP
php对数组排序的简单实例
2013/12/25 PHP
php静态文件生成类实例分析
2015/01/03 PHP
php+ajax实现无刷新文件上传功能(ajaxuploadfile)
2018/02/11 PHP
Laravel5.0+框架邮件发送功能实现方法图文与实例详解
2019/04/23 PHP
PHP fopen中文文件名乱码问题解决方案
2020/10/28 PHP
javascript 命名空间以提高代码重用性
2008/11/13 Javascript
javascript xml为数据源的下拉框控件
2009/07/07 Javascript
javascript与jquery中跳出循环的区别总结
2013/11/04 Javascript
JS去除字符串两端空格的简单实例
2013/12/27 Javascript
JS实现元素上下左右移动效果
2017/10/18 Javascript
mac上配置Android环境变量的方法
2018/07/08 Javascript
Python使用爬虫爬取静态网页图片的方法详解
2018/06/05 Python
Django实现一对多表模型的跨表查询方法
2018/12/18 Python
纯python进行矩阵的相乘运算的方法示例
2019/07/17 Python
Python Django 实现简单注册功能过程详解
2019/07/29 Python
Python流程控制 if else实现解析
2019/09/02 Python
python设置随机种子实例讲解
2019/09/12 Python
利用matplotlib实现根据实时数据动态更新图形
2019/12/13 Python
利用Python自动化操作AutoCAD的实现
2020/04/01 Python
python3 循环读取excel文件并写入json操作
2020/07/14 Python
Expedia爱尔兰:酒店、机票、租车及廉价假期
2017/01/02 全球购物
Crabtree & Evelyn英国官网:瑰珀翠护手霜、香水、沐浴和身体护理
2018/04/26 全球购物
政法大学毕业生自荐信范文
2014/01/01 职场文书
优秀交警事迹材料
2014/01/26 职场文书
篮球比赛策划方案
2014/06/05 职场文书
公务员上班玩游戏检讨书
2014/09/17 职场文书
参观邀请函范文
2015/02/02 职场文书
2015年后勤工作总结范文
2015/04/08 职场文书
2015年秋季开学典礼校长致辞
2015/07/16 职场文书
幼儿园奖惩制度范本
2015/08/05 职场文书
pytest配置文件pytest.ini的详细使用
2021/04/17 Python
Python自动化测试PO模型封装过程详解
2021/06/22 Python
python接口测试返回数据为字典取值方式
2022/02/12 Python