通过源码解析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 相关文章推荐
一个可以删除字符串中HTML标记的PHP函数
Oct 09 PHP
php 字符串函数收集
Mar 29 PHP
php购物车实现方法
Jan 03 PHP
php判断一个数组是否为有序的方法
Mar 27 PHP
8个PHP数组面试题
Jun 23 PHP
ThinkPHP表单令牌错误的相关解决方法分析
May 20 PHP
Yii列表定义与使用分页方法小结(3种方法)
Jul 15 PHP
PHP 芝麻信用接入的注意事项
Dec 01 PHP
Mac下php 5升级到php 7的步骤详解
Apr 26 PHP
php中的异常和错误浅析
May 03 PHP
PHP实现对文件锁进行加锁、解锁操作的方法
Jul 04 PHP
PHP开发API接口签名生成及验证操作示例
May 27 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
使用 MySQL 开始 PHP 会话
2006/12/21 PHP
PHP extract 将数组拆分成多个变量的函数
2010/06/30 PHP
php设计模式 Adapter(适配器模式)
2011/06/26 PHP
php使用array_rand()函数从数组中随机选择一个或多个元素
2014/04/28 PHP
学习php设计模式 php实现工厂模式(factory)
2015/12/07 PHP
laravel validate 设置为中文的例子(验证提示为中文)
2019/09/29 PHP
语义化 H1 标签
2008/01/14 Javascript
JS获取父节点方法
2009/08/20 Javascript
javascript 同时在IE和FireFox获取KeyCode的代码
2010/02/07 Javascript
Colortip基于jquery的信息提示框插件在IE6下面的显示问题修正方法
2010/12/06 Javascript
JS实现的省份级联实例代码
2013/06/24 Javascript
javascript制作loading动画效果 loading效果
2014/01/14 Javascript
node.js中的url.format方法使用说明
2014/12/10 Javascript
jQuery实现TAB风格的全国省份城市滑动切换效果代码
2015/08/24 Javascript
详解JavaScript中|单竖杠运算符的使用方法
2016/05/23 Javascript
js截取字符串功能的实现方法
2017/09/27 Javascript
js实现会跳动的日历效果(完整实例)
2017/10/18 Javascript
js实现随机点名系统(实例讲解)
2017/10/18 Javascript
详解JSON Web Token 入门教程
2018/07/30 Javascript
微信小程序结合mock.js实现后台模拟及调试
2019/03/28 Javascript
vue实现带复选框的树形菜单
2019/05/27 Javascript
nodejs nedb 封装库与使用方法示例
2020/02/06 NodeJs
跟老齐学Python之集合的关系
2014/09/24 Python
使用Python开发windows GUI程序入门实例
2014/10/23 Python
python2.7 mayavi 安装图文教程(推荐)
2017/06/22 Python
Python使用pymysql从MySQL数据库中读出数据的方法
2018/07/25 Python
python如何求解两数的最大公约数
2018/09/27 Python
python list转置和前后反转的例子
2019/08/26 Python
python实现的按要求生成手机号功能示例
2019/10/08 Python
python 使用opencv 把视频分割成图片示例
2019/12/12 Python
python中如何使用insert函数
2020/01/09 Python
HTML5 Canvas 绘图——使用 Canvas 绘制图形图文教程 使用html5 canvas 绘制精美的图
2015/08/31 HTML / CSS
英国最大的美妆产品在线零售商之一:Beauty Bay
2017/09/29 全球购物
如何获取某个日期是当月的最后一天
2013/12/05 面试题
体育学院毕业生自荐信
2013/11/03 职场文书
师德自我剖析材料范文
2014/10/06 职场文书