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实现的太平洋时间和北京时间互转的自定义函数分享
Aug 19 PHP
一款简单实用的php操作mysql数据库类
Dec 08 PHP
jQuery Mobile + PHP实现文件上传
Dec 12 PHP
php+mysqli数据库连接的两种方式
Jan 28 PHP
Laravel 5框架学习之日期,Mutator 和 Scope
Apr 08 PHP
thinkPHP自动验证、自动添加及表单错误问题分析
Oct 17 PHP
php版微信小店调用api示例代码
Nov 12 PHP
原生php实现excel文件读写的方法分析
Apr 25 PHP
深入理解 PHP7 中全新的 zval 容器和引用计数机制
Oct 15 PHP
PHP设计模式之抽象工厂模式实例分析
Mar 25 PHP
PHP 结合 Boostrap 结合 js 实现学生列表删除编辑及搜索功能
May 21 PHP
php实现通过stomp协议连接ActiveMQ操作示例
Feb 23 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
怎样在UNIX系统下安装MySQL
2006/10/09 PHP
php实现微信扫码支付
2017/03/26 PHP
PHP正则之正向预查与反向预查讲解与实例
2020/04/06 PHP
Javascript中的相等与不等运算
2010/04/25 Javascript
js处理json以及字符串的比较等常用操作
2013/09/08 Javascript
javascript中数组array及string的方法总结
2014/11/28 Javascript
推荐6款基于jQuery实现图片效果插件
2014/12/07 Javascript
JS实现图片产生波纹一样flash效果的方法
2015/02/27 Javascript
jquery实现动态改变div宽度和高度
2015/05/08 Javascript
JavaScript数组迭代器实例分析
2015/06/09 Javascript
简单实现限制uploadify上传个数
2015/11/16 Javascript
Bootstrap前端开发案例二
2016/06/17 Javascript
JavaScript每天必学之基础知识
2016/09/17 Javascript
node.js基于express使用websocket的方法
2017/11/09 Javascript
微信小程序使用modal组件弹出对话框功能示例
2017/11/29 Javascript
vue webpack打包优化操作技巧
2018/02/22 Javascript
JS实现页面侧边栏效果探究
2021/01/08 Javascript
[01:53]3.19 DOTA2发布会 现场精彩Coser表演
2014/03/25 DOTA
[02:08]什么藏在DOTA2 TI9“小紫本”里?斧王历险记告诉你!
2019/05/17 DOTA
python统计日志ip访问数的方法
2015/07/06 Python
Python 3.6 性能测试框架Locust安装及使用方法(详解)
2017/10/11 Python
浅谈Python peewee 使用经验
2017/10/20 Python
django使用xlwt导出excel文件实例代码
2018/02/06 Python
windows下安装Python的XlsxWriter模块方法
2018/05/03 Python
win7下python3.6安装配置方法图文教程
2018/07/31 Python
Python requests设置代理的方法步骤
2020/02/23 Python
Python 解析简单的XML数据
2020/07/24 Python
利用Node实现HTML5离线存储的方法
2020/10/16 HTML / CSS
优秀员工自荐信范文
2013/10/05 职场文书
大学应届生求职简历的自我评价
2013/10/08 职场文书
高中毕业的自我鉴定
2013/12/09 职场文书
小学体育教学反思
2014/01/31 职场文书
小学生五年级大队长竞选发言稿
2014/09/12 职场文书
2015年青年教师工作总结
2015/05/25 职场文书
2016年度基层党建工作公开承诺书
2016/03/25 职场文书
使用 CSS 构建强大且酷炫的粒子动画效果
2022/08/14 HTML / CSS