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 相关文章推荐
消息持续发送的完整例子
Oct 09 PHP
PHP 字符串 小常识
Jun 05 PHP
php基础教程 php内置函数实例教程
Aug 21 PHP
php导出excel格式数据问题
Mar 11 PHP
PHP+MYSQL会员系统的开发实例教程
Aug 23 PHP
php生成唯一的订单函数分享
Feb 02 PHP
Apache连接PHP后无法启动问题解决思路
Jun 18 PHP
php实现的数字验证码及数字运算验证码
Jul 30 PHP
Zend Framework入门教程之Zend_Db数据库操作详解
Dec 08 PHP
thinkphp ajaxfileupload实现异步上传图片的示例
Aug 28 PHP
PHP示例演示发送邮件给某个邮箱
Apr 03 PHP
php使用Swoole实现毫秒级定时任务的方法
Sep 04 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
Linux下CoreSeek及PHP扩展模块的安装
2012/09/23 PHP
PHP用strstr()函数阻止垃圾评论(通过判断a标记)
2013/09/28 PHP
JS 实现BASE64_ENCODE和BASE64_DECODE(实例代码)
2013/11/13 Javascript
js中replace的用法总结
2013/12/27 Javascript
jquery遍历checkbox介绍
2014/02/21 Javascript
jQuery中ajax的get()方法用法实例
2014/12/26 Javascript
Javascript基础教程之if条件语句
2015/01/18 Javascript
JS+CSS实现简单的二级下拉导航菜单效果
2015/09/21 Javascript
jquery实现可自动判断位置的弹出层效果代码
2015/10/12 Javascript
浅谈javascript中new操作符的原理
2016/06/07 Javascript
Node.js的特点详解
2017/02/03 Javascript
js简单实现网页换肤功能
2017/04/07 Javascript
用js实现before和after伪类的样式修改的示例代码
2017/09/07 Javascript
vue项目中的webpack-dev-sever配置方法
2017/12/14 Javascript
Vue插槽原理与用法详解
2019/03/05 Javascript
vue-cli打包后本地运行dist文件中的index.html操作
2020/08/12 Javascript
微信小程序实现页面左右滑动
2020/11/16 Javascript
python通过加号运算符操作列表的方法
2015/07/28 Python
python实现中文转换url编码的方法
2016/06/14 Python
python字符串和常用数据结构知识总结
2019/05/21 Python
python flask web服务实现更换默认端口和IP的方法
2019/07/26 Python
Django 路由层URLconf的实现
2019/12/30 Python
通过实例解析Python文件操作实现步骤
2020/09/21 Python
Django生成数据库及添加用户报错解决方案
2020/10/09 Python
python中编写函数并调用的知识点总结
2021/01/13 Python
H5离线存储Manifest原理及使用
2020/04/28 HTML / CSS
希尔顿酒店中国网站:Hilton中国
2017/03/11 全球购物
英国第一摩托车和摩托车越野配件商店:GhostBikes
2019/03/10 全球购物
机械专业求职信范文
2014/07/15 职场文书
2014财务年终工作总结
2014/12/08 职场文书
中秋节晚会开场白
2015/05/29 职场文书
尼克胡哲观后感
2015/06/08 职场文书
七年级英语教学反思
2016/02/15 职场文书
实习报告范文之电话客服岗位
2019/07/26 职场文书
深入浅析Redis 集群伸缩原理
2021/05/15 Redis
利用Python实现模拟登录知乎
2022/05/25 Python