通过源码解析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 相关文章推荐
source.php查看源文件
Dec 09 PHP
excellent!――ASCII Art(由目标图象生成ascii)
Feb 20 PHP
深入解析php之sphinx
May 15 PHP
PHP中的函数-- foreach()的用法详解
Jun 24 PHP
完美的2个php检测字符串是否是utf-8编码函数分享
Jul 28 PHP
PHP Mysqli 常用代码集合
Nov 12 PHP
PHP Socket网络操作类定义与用法示例
Aug 30 PHP
PHP实现的链式队列结构示例
Sep 15 PHP
利用PHP扩展Xhprof分析项目性能实践教程
Sep 05 PHP
ThinkPHP框架下微信支付功能总结踩坑笔记
Apr 10 PHP
php伪静态验证码不显示的解决方案
Sep 26 PHP
PHP 对象继承原理与简单用法示例
Apr 21 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
星际争霸 Starcraft 编年史
2020/03/14 星际争霸
php 数组随机取值的简单实例
2016/05/23 PHP
PHP安装GeoIP扩展根据IP获取地理位置及计算距离的方法
2016/07/01 PHP
golang与PHP输出excel示例
2016/07/22 PHP
Laravel Eloquent分表方法并使用模型关联的实现
2019/11/25 PHP
Google韩国首页图标动画效果
2007/08/26 Javascript
一个简单的js鼠标划过切换效果
2010/06/30 Javascript
基于jquery实现的上传图片及图片大小验证、图片预览效果代码
2011/04/12 Javascript
jQuery中setTimeout的几种使用方法小结
2013/04/07 Javascript
javascript针对cookie的基本操作实例详解
2015/11/30 Javascript
使用Ajax生成的Excel文件并下载的实例
2016/11/21 Javascript
vue中将网页打印成pdf实例代码
2017/06/15 Javascript
利用JavaScript如何查询某个值是否数组内
2017/07/30 Javascript
元素全屏的设置与监听实例
2017/11/28 Javascript
基于three.js编写的一个项目类示例代码
2018/01/05 Javascript
js事件on动态绑定数据,绑定多个事件的方法
2018/09/15 Javascript
Vue 列表上下过渡效果的实例代码
2019/06/25 Javascript
Element-ui DatePicker显示周数的方法示例
2019/07/19 Javascript
JavaScript实现简单的图片切换功能(实例代码)
2020/04/10 Javascript
夯基础之手撕javascript继承详解
2020/11/09 Javascript
[04:29]DOTA2亚洲邀请赛小组赛第一日 TOP10精彩集锦
2015/02/01 DOTA
在Python中使用SQLite的简单教程
2015/04/29 Python
python基于socket实现网络广播的方法
2015/04/29 Python
浅谈终端直接执行py文件,不需要python命令
2017/01/23 Python
Python爬虫通过替换http request header来欺骗浏览器实现登录功能
2018/01/07 Python
Python实现的字典值比较功能示例
2018/01/08 Python
Python静态类型检查新工具之pyright 使用指南
2019/04/26 Python
Python collections模块使用方法详解
2019/08/28 Python
tensorflow 实现从checkpoint中获取graph信息
2020/02/10 Python
突袭HTML5之Javascript API扩展2—地理信息服务及地理位置API学习
2013/01/31 HTML / CSS
文案策划求职信
2014/03/18 职场文书
岗位职责说明书模板
2014/07/30 职场文书
先进事迹材料怎么写
2014/12/30 职场文书
导游词之徐州云龙湖
2019/11/19 职场文书
总结Python连接CS2000的详细步骤
2021/06/23 Python
用Python实现屏幕截图详解
2022/01/22 Python