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 相关文章推荐
教你IIS6的PHP最佳配置方法
Sep 05 PHP
php环境配置 php5 MySQL5 apache2 phpmyadmin安装与配置图文教程
Mar 16 PHP
PHP字符转义相关函数小结(php下的转义字符串)
Apr 12 PHP
PHP 获取目录下的图片并随机显示的代码
Dec 28 PHP
php入门学习知识点一 PHP与MYSql连接与查询
Jul 14 PHP
PHP实例分享判断客户端是否使用代理服务器及其匿名级别
Jun 04 PHP
thinkphp3.2中Lite文件替换框架入口文件或应用入口文件的方法
May 21 PHP
php 生成Tab键或逗号分隔的CSV
Sep 24 PHP
详解PHP编码转换函数应用技巧
Oct 22 PHP
PHP获取input输入框中的值去数据库比较显示出来
Nov 16 PHP
PHP fprintf()函数用法讲解
Feb 16 PHP
phpStorm+XDebug+chrome 配置详解
Apr 01 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使用glob函数遍历目录或文件夹的方法
2014/12/16 PHP
php连接MSsql server的五种方法总结
2018/03/04 PHP
Javascript 设计模式(二) 闭包
2010/05/26 Javascript
初窥JQuery(二) 事件机制(1)
2010/11/25 Javascript
JScript分割字符串示例代码
2013/09/04 Javascript
js实现图片在未加载完成前显示加载中字样
2014/09/03 Javascript
jquery判断至少有一个checkbox被选中的方法
2015/06/05 Javascript
JavaScript数据类型学习笔记分享
2016/09/01 Javascript
js微信支付实现代码
2016/12/22 Javascript
基于jQuery实现选项卡效果
2017/01/04 Javascript
基于jquery日历价格、库存等设置插件
2020/07/05 jQuery
通过命令行生成vue项目框架的方法
2017/07/12 Javascript
JavaScript全屏和退出全屏事件总结(附代码)
2017/08/17 Javascript
微信小程序视图template模板引用的实例详解
2017/09/20 Javascript
利用JQUERY实现多个AJAX请求等待的实例
2017/12/14 jQuery
jackson解析json字符串,首字母大写会自动转为小写的方法
2017/12/22 Javascript
Vue filter介绍及详细使用
2018/04/04 Javascript
使用淘宝镜像cnpm安装Vue.js的图文教程
2018/05/17 Javascript
如何使用CSS3和JQuery easing 插件制作绚丽菜单
2019/06/18 jQuery
JavaScript对象字面量和构造函数原理与用法详解
2020/04/18 Javascript
[42:56]VGJ.S vs Serenity 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
Python多线程编程(四):使用Lock互斥锁
2015/04/05 Python
python用10行代码实现对黄色图片的检测功能
2015/08/10 Python
Python自动化测试Eclipse+Pydev 搭建开发环境
2016/08/15 Python
详解python statistics模块及函数用法
2019/10/27 Python
Tensorflow:转置函数 transpose的使用详解
2020/02/11 Python
python 轮询执行某函数的2种方式
2020/05/03 Python
CSS3实现可爱的小黄人动画
2016/07/11 HTML / CSS
CSS3实现div从下往上滑入滑出效果示例
2020/04/28 HTML / CSS
职高毕业生自我鉴定
2013/10/21 职场文书
保洁主管岗位职责
2013/11/20 职场文书
2014年初中班主任工作总结
2014/11/08 职场文书
2015年学校综合治理工作总结
2015/07/20 职场文书
谢师宴家长答谢词
2015/09/30 职场文书
幼儿园班级管理心得体会
2016/01/07 职场文书
旅游安全责任协议书
2016/03/22 职场文书