通过源码解析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 相关文章推荐
复杂检索数据并分页显示的处理方法
Oct 09 PHP
Zend Studio for Eclipse的java.lang.NullPointerException错误的解决方法
Dec 06 PHP
phpMyadmin 用户权限中英对照
Apr 02 PHP
php数据类型判断函数有哪些
Sep 23 PHP
php 判断是否是中文/英文/数字示例代码
Sep 30 PHP
php strnatcmp()函数的用法总结
Nov 27 PHP
PHP 导出Excel示例分享
Aug 18 PHP
ThinkPHP文件上传实例教程
Aug 22 PHP
培养自己的php编码规范
Sep 28 PHP
PHP生成图片验证码功能示例
Jan 12 PHP
详解PHP使用Redis存储session时的一个Warning定位
Jul 05 PHP
PHP操作Redis常用技巧总结
Apr 24 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
咖啡因含量是由谁决定的?低因咖啡怎么来?低因咖啡适合什么人喝
2021/03/06 新手入门
PHP中的替代语法介绍
2015/01/09 PHP
ThinkPHP中数据操作案例分析
2015/09/27 PHP
PHP和C#可共用的可逆加密算法详解
2015/10/26 PHP
PHP常见错误提示含义解释(实用!值得收藏)
2016/04/25 PHP
PHP Header失效的原因分析及解决方法
2016/11/16 PHP
通过PHP设置BugFree获取邮箱通知
2019/04/25 PHP
JQuery中阻止事件冒泡几种方式及其区别介绍
2014/01/15 Javascript
Nodejs实现的一个静态服务器实例
2014/12/06 NodeJs
简介JavaScript中search()方法的使用
2015/06/06 Javascript
jQuery实现鼠标划过添加和删除class的方法
2015/06/26 Javascript
Jquery zTree 树控件异步加载操作
2016/02/25 Javascript
JS组件系列之JS组件封装过程详解
2017/04/28 Javascript
清空元素html("") innerHTML="" 与 empty()的区别和应用(推荐)
2017/08/14 Javascript
微信小程序删除处理详解
2017/08/16 Javascript
浅谈Webpack核心模块tapable解析
2018/09/11 Javascript
详解微信小程序scroll-view横向滚动的实践踩坑及隐藏其滚动条的实现
2019/03/14 Javascript
vue使用exif获取图片旋转,压缩的示例代码
2020/12/11 Vue.js
Python中的id()函数指的什么
2017/10/17 Python
python学习笔记--将python源文件打包成exe文件(pyinstaller)
2018/05/26 Python
python3 property装饰器实现原理与用法示例
2019/05/15 Python
Python +Selenium解决图片验证码登录或注册问题(推荐)
2020/02/09 Python
Python在终端通过pip安装好包以后在Pycharm中依然无法使用的问题(三种解决方案)
2020/03/10 Python
django 模型字段设置默认值代码
2020/07/15 Python
Python json格式化打印实现过程解析
2020/07/21 Python
Python 开发工具通过 agent 代理使用的方法
2020/09/27 Python
Strawberrynet草莓网新加坡站:护肤、彩妆、香水及美发产品
2018/08/31 全球购物
现代生活方式的家具和装饰:Dot & Bo
2018/12/26 全球购物
美国家居装饰购物网站:Amanda Lindroth
2020/03/25 全球购物
大学生应聘自荐信
2013/10/11 职场文书
行政助理岗位职责范文
2013/12/03 职场文书
销售员自我评价
2015/03/11 职场文书
山楂树之恋观后感
2015/06/11 职场文书
交通安全教育心得体会
2016/01/15 职场文书
详细介绍python操作RabbitMq
2022/04/12 Python
详解ZABBIX监控ESXI主机的问题
2022/06/21 Servers