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 相关文章推荐
从零开始 教你如何搭建Discuz!4.1论坛
Jul 07 PHP
社区(php&&mysql)二
Oct 09 PHP
PHP+DBM的同学录程序(5)
Oct 09 PHP
快速配置PHPMyAdmin方法
Jun 05 PHP
基于PHP读取TXT文件向数据库导入海量数据的方法
Apr 23 PHP
php addslashes 利用递归实现使用反斜线引用字符串
Aug 05 PHP
PHP中批量生成静态html(命令行下运行PHP)
Apr 19 PHP
php中strstr、strrchr、substr、stristr四个函数的区别总结
Sep 22 PHP
php cookie中点号(句号)自动转为下划线问题
Oct 21 PHP
win7系统配置php+Apache+mysql环境的方法
Aug 21 PHP
PHP实现通过二维数组键值获取一维键名操作示例
Oct 11 PHP
php实现图片压缩处理
Sep 09 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 zip文件解压类代码
2009/12/02 PHP
PHP调用存储过程返回值不一致问题的解决方法分析
2016/04/26 PHP
php多进程并发编程防止出现僵尸进程的方法分析
2020/02/28 PHP
基于jQuery中对数组进行操作的方法
2013/04/16 Javascript
JavaScript声明变量时为什么要加var关键字
2014/09/29 Javascript
JavaScript检测鼠标移动方向的方法
2015/05/22 Javascript
使用javascript提交form表单方法汇总
2015/06/25 Javascript
AngularJS学习笔记之依赖注入详解
2016/05/16 Javascript
WebView启动支付宝客户端支付失败的问题小结
2017/01/11 Javascript
详解AngularJs ui-router 路由的简单介绍
2017/04/26 Javascript
nodejs使用express获取get和post传值及session验证的方法
2017/11/09 NodeJs
Vue-cli项目获取本地json文件数据的实例
2018/03/07 Javascript
使用nodejs分离html文件里的js和css详解
2019/04/12 NodeJs
React Native 混合开发多入口加载方式详解
2019/09/23 Javascript
JS数组方法reverse()用法实例分析
2020/01/18 Javascript
python time模块用法实例详解
2014/09/11 Python
python实现发送和获取手机短信验证码
2016/01/15 Python
python类:class创建、数据方法属性及访问控制详解
2016/07/25 Python
使用python爬虫实现网络股票信息爬取的demo
2018/01/05 Python
Python实现曲线拟合操作示例【基于numpy,scipy,matplotlib库】
2018/07/12 Python
pygame游戏之旅 python和pygame安装教程
2018/11/20 Python
详解python编译器和解释器的区别
2019/06/24 Python
Python学习笔记之For循环用法详解
2019/08/14 Python
flask 实现上传图片并缩放作为头像的例子
2020/01/09 Python
python用WxPython库实现无边框窗体和透明窗体实现方法详解
2020/02/21 Python
Python tkinter布局与按钮间距设置方式
2020/03/04 Python
将 Ubuntu 16 和 18 上的 python 升级到最新 python3.8 的方法教程
2020/03/11 Python
Python通过socketserver处理多个链接
2020/03/18 Python
大二自我鉴定范文
2013/10/05 职场文书
培训心得体会
2013/12/29 职场文书
总经理助理职责
2014/02/04 职场文书
运动会方阵口号
2014/06/07 职场文书
聘用意向书
2014/07/29 职场文书
银行员工考核评语
2014/12/31 职场文书
又涨知识了,自律到底多重要?
2019/06/27 职场文书
源码安装apache脚本部署过程详解
2022/09/23 Servers