通过源码解析Laravel的依赖注入


Posted in PHP onJanuary 22, 2018

前言

众所周知,php的框架数不胜数,近几年,一个以优雅著称的框架,渐渐被国内phper所知道,并且开始使用,但是larave有一个很明显的缺点就是,他的文档内容少的可怜。

本文将给大家详细介绍关于Laravel依赖注入的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。

在 Laravel 的控制器的构造方法或者成员方法,都可以通过类型约束的方式使用依赖注入,如:

public function store(Request $request)
{
 //TODO
}

这里 $request 参数就使用了类型约束,Request 是一个类:\Illuminate\Http\Request,表示参数必须是这个类或子类。

本文通过分析 Laravel 的源码,看为什么方法中不需要传入实例就可以直接使用 Request 呢?只是框架自动帮我们实例化并传参了。

1.路由定义

从源头开始看起,在路由定义文件中定义了这么一个路由:

Route::resource('/role', 'Admin\RoleController');

这是一个资源型的路由,Laravel 会自动生成增删改查的路由入口。

通过源码解析Laravel的依赖注入

本文开头的 store 方法就是一个控制器的方法,图中可见路由定义的 Action 也是:App\Http\Controllers\Admin\RoleController@store

路由方法解析

根据路由定义找到控制器和方法,执行具体的方法在 dispatch 方法中实现。

(文件:vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php)

public function dispatch(Route $route, $controller, $method)
{
 $parameters = $this->resolveClassMethodDependencies(
  $route->parametersWithoutNulls(), $controller, $method
 );
 
 if (method_exists($controller, 'callAction')) {
  return $controller->callAction($method, $parameters);
 }
 
 return $controller->{$method}(...array_values($parameters));
}

首先 resolveClassMethodDependencies 方法,“顾名思义”是根据类的方法参数获取依赖对象,然后再调用类的方法并把对象参数注入。

如果有多个依赖对象,也会 foreach 依次解析出来作为参数注入。

获取依赖对象示例的代码:

protected function resolveClassMethodDependencies(array $parameters, $instance, $method)
{
 if (! method_exists($instance, $method)) {
  return $parameters;
 }
 
 return $this->resolveMethodDependencies(
  $parameters, new ReflectionMethod($instance, $method)
 );
}

这里重点就是用到了 PHP 的反射,注意 RelectionMethod 方法,它获取到类的方法参数列表,可以知道参数的类型约束,参数名称等等。

这里的 $instance 参数就是 RoleController 控制器类,$method 参数就是方法名称 strore.

2.获取依赖对象的示例

从方法的参数中获取了依赖对象的约束类型,就可以实例化这个依赖的对象。

protected function transformDependency(ReflectionParameter $parameter, $parameters)
{
 $class = $parameter->getClass(); 
 // If the parameter has a type-hinted class, we will check to see if it is already in
 // the list of parameters. If it is we will just skip it as it is probably a model
 // binding and we do not want to mess with those; otherwise, we resolve it here.
 if ($class && ! $this->alreadyInParameters($class->name, $parameters)) {
  return $parameter->isDefaultValueAvailable()
   ? $parameter->getDefaultValue()
   : $this->container->make($class->name);
 }
}

根据类名从容器中获取对象,这个绑定对象实例的过程在服务提供者中先定义和了。

然后把实例化的对象传入到 store 方法中,就可以使用依赖的对象了。

3.关于 PHP 反射

举个使用 ReflectionMethod 的例子。

class Demo
{
 private $request;
 public function store(Request $request)
 {
 }
}

打印出 new ReflectionMethod(Demo::class, ‘store') 的内容如图:

通过源码解析Laravel的依赖注入

可以得出这个方法的参数列表,参数的约束类型,如 typeHint,Illuminate\Http\Request.

根据类名可以从容器中获取一开始通过服务提供者绑定的实例。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
PHP验证码类代码( 最新修改,完全定制化! )
Dec 02 PHP
简单的cookie计数器实现源码
Jun 07 PHP
PHP直接修改表内容DataGrid功能实现代码
Sep 24 PHP
php获取当前页面完整URL地址
Dec 30 PHP
PHP中each与list用法分析
Jan 08 PHP
php读取txt文件并将数据插入到数据库
Feb 23 PHP
如何离线执行php任务
Feb 21 PHP
PHP Class SoapClient not found解决方法
Jan 20 PHP
lnmp安装多版本PHP共存的方法详解
Aug 02 PHP
PHP+iframe模拟Ajax上传文件功能示例
Jul 02 PHP
php实现快速对二维数组某一列进行组装的方法小结
Dec 04 PHP
Laravel框架处理用户的请求操作详解
Dec 20 PHP
phpstorm 正则匹配删除空行、注释行(替换注释行为空行)
Jan 21 #PHP
php语言注释,单行注释和多行注释
Jan 21 #PHP
PHP注释语法规范与命名规范详解篇
Jan 21 #PHP
php nginx 实时输出的简单实现方法
Jan 21 #PHP
Lumen timezone 时区设置方法(慢了8个小时)
Jan 20 #PHP
PHP Class SoapClient not found解决方法
Jan 20 #PHP
tp5(thinkPHP5)操作mongoDB数据库的方法
Jan 20 #PHP
You might like
php自动获取字符串编码函数mb_detect_encoding
2011/05/31 PHP
PHP 第二节 数据类型之数组
2012/04/28 PHP
PHP设计模式之迭代器模式的深入解析
2013/06/13 PHP
JavaScript 学习小结(适合新手参考)
2009/07/30 Javascript
JavaScript Scoping and Hoisting 翻译
2012/07/03 Javascript
写自已的js类库需要的核心代码
2012/07/16 Javascript
jquery遍历数组与筛选数组的方法
2013/11/05 Javascript
JQGrid的用法解析(列编辑,添加行,删除行)
2013/11/08 Javascript
JS实现超简单的仿QQ折叠菜单效果
2015/09/21 Javascript
JS组件Bootstrap Select2使用方法解析
2016/05/30 Javascript
layui 监听表格复选框选中值的方法
2018/08/15 Javascript
vue实现弹框遮罩点击其他区域弹框关闭及v-if与v-show的区别介绍
2018/09/29 Javascript
CKEditor4配置与开发详细中文说明文档
2018/10/08 Javascript
JS实现在线ps功能详解
2019/07/31 Javascript
JavaScript图像放大镜效果实现方法详解
2020/06/28 Javascript
Nodejs 数组的队列以及forEach的应用详解
2021/02/25 NodeJs
[04:45]上海特级锦标赛主赛事第三日TOP10
2016/03/05 DOTA
Python实现的微信公众号群发图片与文本消息功能实例详解
2017/06/30 Python
Python温度转换实例分析
2018/01/17 Python
Pytorch 实现focal_loss 多类别和二分类示例
2020/01/14 Python
jupyter notebook中新建cell的方法与快捷键操作
2020/04/22 Python
如何利用Python 进行边缘检测
2020/10/14 Python
python3中数组逆序输出方法
2020/12/01 Python
html5实现滑块功能之type="range"属性
2020/02/18 HTML / CSS
芬兰汽车配件商店:Autonvaraosat24
2017/01/30 全球购物
MIKI HOUSE美国官方网上商店:日本领先的婴儿和儿童高级时装品牌
2020/06/21 全球购物
荣耀商城:HIHONOR
2020/11/03 全球购物
你懂得怎么写自荐信吗?
2013/12/27 职场文书
给国外客户的邀请函
2014/01/30 职场文书
万年牢教学反思
2014/02/15 职场文书
药品业务员岗位职责
2014/04/17 职场文书
融资租赁计划书
2014/04/29 职场文书
投资申请报告
2015/05/19 职场文书
职位证明模板
2015/06/23 职场文书
《作风建设永远在路上》心得体会
2016/01/21 职场文书
MySQL 百万级数据的4种查询优化方式
2021/06/07 MySQL