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新手上路(二)
Oct 09 PHP
一个更简单的无限级分类菜单代码
Jan 16 PHP
队列在编程中的实际应用(php)
Sep 04 PHP
Zend Framework中的简单工厂模式 图文
Jul 10 PHP
PHP中的函数-- foreach()的用法详解
Jun 24 PHP
兼容ie6浏览器的php下载文件代码分享
Jul 14 PHP
ThinkPHP上使用多说评论插件的方法
Oct 31 PHP
PHP模板引擎Smarty中变量的使用方法示例
Apr 11 PHP
PHP 的比较运算与逻辑运算详解
May 12 PHP
PHP实现的文件操作类及文件下载功能示例
Dec 24 PHP
浅谈php中变量的数据类型判断函数
Mar 04 PHP
laravel批量生成假数据的方法
Oct 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
ppk谈JavaScript style属性
2008/10/10 Javascript
js 纯数字不重复排列的另类方法
2010/07/17 Javascript
JS维吉尼亚密码算法实现代码
2010/11/09 Javascript
JQuery实现用户名无刷新验证的小例子
2013/03/22 Javascript
nodejs下打包模块archiver详解
2014/12/03 NodeJs
jQuery动画效果相关方法实例分析
2015/12/31 Javascript
JavaScript实现相册弹窗功能(zepto.js)
2016/06/21 Javascript
利用原生JS自动生成文章标题树的实例
2016/08/22 Javascript
jQuery实现磁力图片跟随效果完整示例
2016/09/16 Javascript
Bootstrap 模态框(Modal)插件代码解析
2016/12/21 Javascript
jQuery电话号码验证实例
2017/01/05 Javascript
移动端界面的适配
2017/01/11 Javascript
JavaScript实现QQ聊天消息展示和评论提交功能
2017/05/22 Javascript
浅谈Vue父子组件和非父子组件传值问题
2017/08/22 Javascript
原生js实现简单的模态框示例
2017/09/08 Javascript
ES10的13个新特性示例(小结)
2019/09/23 Javascript
jQuery擦除插件eraser使用方法详解
2020/01/11 jQuery
Python EOL while scanning string literal问题解决方法
2020/09/18 Python
使用 Python 实现微信公众号粉丝迁移流程
2018/01/03 Python
Python pymongo模块用法示例
2018/03/31 Python
解决python写入mysql中datetime类型遇到的问题
2018/06/21 Python
利用Python实现Shp格式向GeoJSON的转换方法
2019/07/09 Python
Python对接 xray 和微信实现自动告警
2019/09/17 Python
Python Pickle 实现在同一个文件中序列化多个对象
2019/12/30 Python
python super函数使用方法详解
2020/02/14 Python
python 统计list中各个元素出现的次数的几种方法
2021/02/20 Python
纯css3实现图片翻牌特效
2015/03/10 HTML / CSS
英国女士和男士时尚服装网上购物:Top Labels Online
2018/03/25 全球购物
生产车间班组长岗位职责
2014/01/06 职场文书
十佳大学生村官事迹
2014/01/09 职场文书
汇源肾宝广告词
2014/03/20 职场文书
服务员态度差检讨书
2014/10/28 职场文书
2014年维稳工作总结
2014/11/18 职场文书
2015年暑期社会实践活动总结
2015/03/27 职场文书
2019中小学生安全过暑期倡议书
2019/06/24 职场文书
django项目、vue项目部署云服务器的详细过程
2022/07/23 Servers