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 相关文章推荐
isset和empty的区别
Jan 15 PHP
ie6 动态缩略图不显示的原因
Jun 21 PHP
php面向对象全攻略 (十二) 抽象方法和抽象类
Sep 30 PHP
php程序的国际化实现方法(利用gettext)
Aug 14 PHP
在PHP中设置、使用、删除Cookie的解决方法
May 06 PHP
php更新修改excel中的内容实例代码
Feb 26 PHP
PHP判断来访是搜索引擎蜘蛛还是普通用户的代码小结
Sep 14 PHP
PHP中header用法小结
May 23 PHP
PHP学习笔记之php文件操作
Jun 03 PHP
PHP对象实例化单例方法
Jan 19 PHP
PHP图片裁剪与缩放示例(无损裁剪图片)
Feb 08 PHP
深入解析PHP底层机制及相关原理
Dec 11 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图片自动裁切应付不同尺寸的显示
2014/10/16 PHP
php实现两表合并成新表并且有序排列的方法
2014/12/05 PHP
php通过session防url攻击方法
2014/12/10 PHP
PHP中的替代语法介绍
2015/01/09 PHP
PHP输出日历表代码实例
2015/03/27 PHP
laravel实现上传图片的两种方式小结
2019/10/12 PHP
jquery动态添加删除div 具体实现
2013/07/20 Javascript
jQuery之Deferred对象详解
2014/09/04 Javascript
向JavaScript的数组中添加元素的方法小结
2015/10/24 Javascript
Javascript简单实现面向对象编程继承实例代码
2015/11/27 Javascript
JavaScript对象封装的简单实现方法(3种方法)
2017/01/03 Javascript
深入理解JavaScript创建对象的多种方式以及优缺点
2017/06/01 Javascript
JavaScript实现简单音乐播放器
2020/04/17 Javascript
详解vue为什么要求组件模板只能有一个根元素
2019/07/22 Javascript
vue实现手机号码的校验实例代码(防抖函数的应用场景)
2019/09/05 Javascript
[01:29:31]VP VS VG Supermajor小组赛胜者组第二轮 BO3第一场 6.2
2018/06/03 DOTA
详细介绍Python的鸭子类型
2016/09/12 Python
Python3自动签到 定时任务 判断节假日的实例
2018/11/13 Python
解决pycharm导入本地py文件时,模块下方出现红色波浪线的问题
2020/06/01 Python
处理HTML5新标签的浏览器兼容版问题
2017/03/13 HTML / CSS
巴西男士胡须和头发护理产品商店:Beard
2017/11/13 全球购物
美国最古老的精致书写工具制造商:A.T. Cross(高仕)
2018/01/30 全球购物
Vertbaudet西班牙网上商店:婴儿服装、童装、母婴用品和儿童家具
2019/10/16 全球购物
伦敦最受欢迎的蛋糕店:Konditor & Cook
2019/11/01 全球购物
关于VPN
2012/06/10 面试题
主管职责范文
2013/11/09 职场文书
精彩的推荐信范文
2013/11/26 职场文书
校园餐饮创业计划书
2014/01/10 职场文书
农民致富事迹材料
2014/01/23 职场文书
安全生产先进个人材料
2014/02/06 职场文书
开学典礼感言
2014/02/16 职场文书
授权收款委托书范本
2014/10/10 职场文书
小马王观后感
2015/06/11 职场文书
六五普法先进个人主要事迹材料
2015/11/03 职场文书
mongoDB数据库索引快速入门指南
2022/03/23 MongoDB
Nginx文件已经存在全局反向代理问题排查记录
2022/07/15 Servers