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 相关文章推荐
层叠菜单的动态生成
Oct 09 PHP
怎样在PHP中通过ADO调用Asscess数据库和COM程序
Oct 09 PHP
php trim 去除空字符的定义与语法介绍
May 31 PHP
不支持fsockopen但支持culr环境下下ucenter与modoer通讯问题
Aug 12 PHP
PHP图片处理类 phpThumb参数用法介绍
Mar 11 PHP
php中的常用魔术方法总结
Aug 02 PHP
PHP中使用imagick实现把PDF转成图片
Jan 26 PHP
php使用post数组的键值创建同名变量并赋值的方法
Apr 03 PHP
php实现修改新闻时删除图片的方法
May 12 PHP
yii分页组件用法实例分析
Dec 28 PHP
PHP.vs.JAVA
Apr 29 PHP
php常用字符串查找函数strstr()与strpos()实例分析
Jun 21 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
PHP获取类中常量,属性,及方法列表的方法
2009/04/09 PHP
跟我学Laravel之请求(Request)的生命周期
2014/10/15 PHP
php生成动态验证码gif图片
2015/10/19 PHP
设定php简写功能的方法
2019/11/28 PHP
说说掌握JavaScript语言的思想前提想学习js的朋友可以看看
2009/04/01 Javascript
表单元素事件 (Form Element Events)
2009/07/17 Javascript
javascript之querySelector和querySelectorAll使用说明
2011/10/09 Javascript
jquery可见性过滤选择器使用示例
2013/06/24 Javascript
JS分页效果示例
2013/10/11 Javascript
Js获取当前日期时间及格式化代码
2016/09/17 Javascript
Vue.js实战之利用vue-router实现跳转页面
2017/04/01 Javascript
判断div滑动到底部的scroll实例代码
2017/11/15 Javascript
详解webpack+express多页站点开发
2017/12/22 Javascript
从组件封装看Vue的作用域插槽的实现
2019/02/12 Javascript
js如何获取访问IP、地区、当前操作浏览器
2019/07/23 Javascript
React冒泡和阻止冒泡的应用详解
2020/08/18 Javascript
解决vscode进行vue格式化,会自动补分号和双引号的问题
2020/10/26 Javascript
基于javascript实现放大镜特效
2020/12/03 Javascript
json.stringify()与json.parse()的区别以及用处
2021/01/25 Javascript
浅谈Python生成器generator之next和send的运行流程(详解)
2017/05/08 Python
python中利用Future对象异步返回结果示例代码
2017/09/07 Python
Python设计模式之代理模式简单示例
2018/01/09 Python
python中时间模块的基本使用教程
2019/05/14 Python
Python定时任务APScheduler的实例实例详解
2019/07/22 Python
基于python实现音乐播放器代码实例
2020/07/01 Python
35款精致的 CSS3 和 HTML5 网页模板 推荐
2012/08/03 HTML / CSS
h5页面背景图很长要有滚动条滑动效果的实现
2021/01/27 HTML / CSS
拉飞逸官网:Lafayette 148 New York
2020/07/15 全球购物
实习生自荐信范文
2013/11/13 职场文书
店长岗位职责
2013/11/21 职场文书
无传销社区工作方案
2014/05/13 职场文书
2015暑期社会实践个人总结
2015/07/13 职场文书
CSS实现章节添加自增序号的方法
2021/06/23 HTML / CSS
Golang中channel的原理解读(推荐)
2021/10/16 Golang
nginx 添加http_stub_status_module模块
2022/05/25 Servers
python实现学员管理系统(面向对象版)
2022/06/05 Python