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 相关文章推荐
第十四节--命名空间
Nov 16 PHP
PHP fgetcsv 定义和用法(附windows与linux下兼容问题)
May 29 PHP
解析PHP的session过期设置
Jun 29 PHP
php中Array2xml类实现数组转化成XML实例
Dec 08 PHP
php实现通过cookie换肤的方法
Jul 13 PHP
基于PHP给大家讲解防刷票的一些技巧
Nov 18 PHP
PHP中addcslashes与stripcslashes函数用法分析
Jan 07 PHP
php mysql_list_dbs()函数用法示例
Mar 29 PHP
PHP中时间加减函数strtotime用法分析
Apr 26 PHP
PHP框架自动加载类文件原理详解
Jun 06 PHP
PHP swoole和redis异步任务实现方法分析
Aug 12 PHP
PHP常用函数之格式化时间操作示例
Oct 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
在JavaScript中调用php程序
2009/03/09 PHP
php 删除cookie方法详解
2014/12/01 PHP
8个必备的PHP功能开发
2015/10/02 PHP
PHP识别二维码的方法(php-zbarcode安装与使用)
2016/07/07 PHP
php+flash+jQuery多图片上传源码分享
2020/07/27 PHP
Mootools 1.2教程 事件处理
2009/09/15 Javascript
ext 同步和异步示例代码
2009/09/18 Javascript
jQuery 行背景颜色的交替显示(隔行变色)实现代码
2009/12/13 Javascript
不同浏览器的怪癖小结
2010/07/11 Javascript
jQuery采用连缀写法实现的折叠菜单效果
2015/09/18 Javascript
JavaScript计划任务后台运行的方法
2015/12/18 Javascript
jQuery实现的给图片点赞+1动画效果(附在线演示及demo源码下载)
2015/12/31 Javascript
JavaScript 节流函数 Throttle 详解
2016/07/04 Javascript
jQuery下拉菜单的实现代码
2016/11/03 Javascript
使用jQuery和ajax代替iframe的方法(详解)
2017/04/12 jQuery
详解JS中的attribute属性
2017/04/25 Javascript
详解Javascript 中的 class、构造函数、工厂函数
2017/12/20 Javascript
一篇文章,教你学会Vue CLI 插件开发
2019/04/17 Javascript
在vue中使用Base64转码的案例
2020/08/07 Javascript
浅谈es6中的元编程
2020/12/01 Javascript
Python 错误和异常小结
2013/10/09 Python
Python实现简单的文件传输与MySQL备份的脚本分享
2016/01/03 Python
Python处理XML格式数据的方法详解
2017/03/21 Python
python中类和实例如何绑定属性与方法示例详解
2017/08/18 Python
开源软件包和环境管理系统Anaconda的安装使用
2017/09/04 Python
Python实现自动为照片添加日期并分类的方法
2017/09/30 Python
分享一下Python数据分析常用的8款工具
2018/04/29 Python
python 多线程重启方法
2019/02/18 Python
python关于矩阵重复赋值覆盖问题的解决方法
2019/07/19 Python
详解用python生成随机数的几种方法
2019/08/04 Python
Delphi笔试题
2016/11/14 面试题
普通大学毕业生自荐信
2013/11/04 职场文书
人力资源经理的岗位职责范本
2014/02/28 职场文书
2015年六一儿童节演讲稿
2015/03/19 职场文书
新郎婚礼致辞
2015/07/27 职场文书
MySQL 常见的数据表设计误区汇总
2021/06/07 MySQL