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 相关文章推荐
BBS(php & mysql)完整版(五)
Oct 09 PHP
apache+php+mysql安装配置方法小结
Aug 01 PHP
smarty 缓存控制前的页面静态化原理
Mar 15 PHP
PHP实现更新中间关联表数据的两种方法
Sep 01 PHP
PHP实现绘制3D扇形统计图及图片缩放实例
Oct 01 PHP
php使用date和strtotime函数输出指定日期的方法
Nov 14 PHP
PHP之密码加密的几种方式
Jul 29 PHP
常见PHP数据库解决方案分析介绍
Sep 24 PHP
php 三元运算符实例详细介绍
Dec 15 PHP
laravel中命名路由的使用方法
Feb 24 PHP
SCP远程VPS快速搬家和WDCP升级php5.3安装memcached和eaccelerator教程
Jul 27 PHP
PHP crypt()函数的用法讲解
Feb 15 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
phpmyadmin操作流程
2006/10/09 PHP
用PHP连mysql和oracle数据库性能比较
2006/10/09 PHP
PHP入门速成教程
2007/03/19 PHP
PHP逐行输出(ob_flush与flush的组合)
2012/02/04 PHP
关于PHP内存溢出问题的解决方法
2013/06/25 PHP
Ajax提交表单时验证码自动验证 php后端验证码检测
2016/07/20 PHP
php图像验证码生成代码
2017/06/08 PHP
详解PHP如何更好的利用PHPstorm的自动提示
2017/08/18 PHP
PHP使用ajax的post方式下载excel文件简单示例
2019/08/06 PHP
javascript实现的动态文字变换
2007/07/28 Javascript
JS随机漂浮广告代码具体实例
2013/11/19 Javascript
Chrome扩展页面动态绑定JS事件提示错误
2014/02/11 Javascript
javascript操作符"!~"详解
2015/02/10 Javascript
使用基于Node.js的构建工具Grunt来发布ASP.NET MVC项目
2016/02/15 Javascript
表单中单选框添加选项和移除选项
2016/07/04 Javascript
D3.js实现柱状图的方法详解
2016/09/21 Javascript
jQuery中Find选择器用法示例
2016/09/21 Javascript
JS实现登录页密码的显示和隐藏功能
2017/12/06 Javascript
谈谈vue中mixin的一点理解
2017/12/12 Javascript
AngularJs点击状态值改变背景色的实例
2017/12/18 Javascript
webpack4 处理SCSS的方法示例
2018/09/03 Javascript
vue解决使用$http获取数据时报错的问题
2019/10/30 Javascript
[03:17]DOTA2英雄基础教程 剧毒术士
2013/12/12 DOTA
[03:42]2018完美盛典-《加冕》
2018/12/16 DOTA
python操作gmail实例
2015/01/14 Python
Python实现文件内容批量追加的方法示例
2017/08/29 Python
Win7 64位下python3.6.5安装配置图文教程
2020/10/27 Python
python3+PyQt5+Qt Designer实现扩展对话框
2018/04/20 Python
Python3 读、写Excel文件的操作方法
2018/10/20 Python
对python字典过滤条件的实例详解
2019/01/22 Python
使用keras2.0 将Merge层改为函数式
2020/05/23 Python
美国眼镜网:GlassesUSA
2017/09/07 全球购物
日本快乐生活方式购物网站:Shop Japan
2018/07/17 全球购物
幼儿园家长评语大全
2014/04/16 职场文书
家庭困难证明
2014/10/12 职场文书
python爬虫selenium模块详解
2021/03/30 Python