通过源码解析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 mvc开发模式的感想
Jun 28 PHP
mysql数据库差异比较的PHP代码
Feb 05 PHP
浅析php过滤html字符串,防止SQL注入的方法
Jul 02 PHP
PHP如何利用P3P实现跨域
Aug 24 PHP
网页上facebook分享功能具体实现
Jan 26 PHP
ThinkPHP使用smarty模板引擎的方法
Jul 01 PHP
php简单定时执行任务的实现方法
Feb 23 PHP
PHP表单提交后引号前自动加反斜杠的原因及三种办法关闭php魔术引号
Sep 30 PHP
Zend Framework教程之Zend_Db_Table用法详解
Mar 21 PHP
thinkPHP模板算术运算相关函数用法分析
Jul 12 PHP
PHP7内核CGI与FastCGI详解
Apr 14 PHP
Laravel Validator 实现两个或多个字段联合索引唯一
May 08 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防盗链的常用方法小结
2010/07/02 PHP
php对数组排序代码分享
2014/02/24 PHP
Win7下手动安装apache2.2、php5.4笔记
2015/04/03 PHP
laravel 数据迁移与 Eloquent ORM的实现方法
2019/04/12 PHP
使用JQuery进行跨域请求
2010/01/25 Javascript
Jquery Ajax请求代码(2)
2011/01/07 Javascript
jquery高效反选具体实现
2013/05/05 Javascript
jQuery 获取和设置select下拉框的值实现代码
2013/11/08 Javascript
下拉框select的绑定示例
2014/09/04 Javascript
node.js中的定时器nextTick()和setImmediate()区别分析
2014/11/26 Javascript
jQuery.position()方法获取不到值的安全替换方法
2015/03/13 Javascript
jquery实现简易的移动端验证表单
2015/11/08 Javascript
angularjs封装$http为factory的方法
2017/05/18 Javascript
javascript获取指定区间范围随机数的方法
2017/09/08 Javascript
深入探索VueJS Scoped CSS 实现原理
2019/09/23 Javascript
[04:10]DOTA2英雄梦之声_第11期_圣堂刺客
2014/06/21 DOTA
python网络编程学习笔记(七):HTML和XHTML解析(HTMLParser、BeautifulSoup)
2014/06/09 Python
跟老齐学Python之集合的关系
2014/09/24 Python
Windows下实现Python2和Python3两个版共存的方法
2015/06/12 Python
Python使用Paramiko模块编写脚本进行远程服务器操作
2016/05/05 Python
深入理解NumPy简明教程---数组2
2016/12/17 Python
python爬取各类文档方法归类汇总
2018/03/22 Python
matlab中实现矩阵删除一行或一列的方法
2018/04/04 Python
详解Django+Uwsgi+Nginx 实现生产环境部署
2018/11/06 Python
python线程池 ThreadPoolExecutor 的用法示例
2020/10/10 Python
Python求区间正整数内所有素数之和的方法实例
2020/10/13 Python
Tory Burch英国官方网站:美国时尚生活品牌
2017/12/06 全球购物
中专生的个人自我评价
2013/12/11 职场文书
集团公司人力资源部岗位职责
2014/01/03 职场文书
工艺工程师岗位职责
2014/03/04 职场文书
党员教师自我剖析材料
2014/09/29 职场文书
建国大业电影观后感
2015/06/01 职场文书
Java常用函数式接口总结
2021/06/29 Java/Android
mysql主从复制的实现步骤
2021/10/24 MySQL
动漫APP软件排行榜前十名,半次元上榜,第一款由腾讯公司推出
2022/03/18 杂记
Linux下使用C语言代码搭建一个简单的HTTP服务器
2022/04/13 Servers