Laravel实现构造函数自动依赖注入的方法


Posted in PHP onMarch 16, 2016

本文实例讲述了Laravel实现构造函数自动依赖注入的方法。分享给大家供大家参考,具体如下:

在Laravel的构造函数中可以实现自动依赖注入,而不需要实例化之前先实例化需要的类,如代码所示:

<?php
namespace Lio\Http\Controllers\Forum;
use Lio\Forum\Replies\ReplyRepository;
use Lio\Forum\Threads\ThreadCreator;
use Lio\Forum\Threads\ThreadCreatorListener;
use Lio\Forum\Threads\ThreadDeleterListener;
use Lio\Forum\Threads\ThreadForm;
use Lio\Forum\Threads\ThreadRepository;
use Lio\Forum\Threads\ThreadUpdaterListener;
use Lio\Http\Controllers\Controller;
use Lio\Tags\TagRepository;
class ForumThreadsController extends Controller implements ThreadCreatorListener, ThreadUpdaterListener, ThreadDeleterListener
{
 protected $threads;
 protected $tags;
 protected $currentSection;
 protected $threadCreator;
 public function __construct(
  ThreadRepository $threads,
  ReplyRepository $replies,
  TagRepository $tags,
  ThreadCreator $threadCreator
 ) {
  $this->threads = $threads;
  $this->tags = $tags;
  $this->threadCreator = $threadCreator;
  $this->replies = $replies;
 }
}

注意构造函数中的几个类型约束,其实并没有地方实例化这个Controller并把这几个类型的参数传进去,Laravel会自动检测类的构造函数中的类型约束参数,并自动识别是否初始化并传入。

源码vendor/illuminate/container/Container.php中的build方法:

$constructor = $reflector->getConstructor();
dump($constructor);

这里会解析类的构造函数,在这里打印看:

Laravel实现构造函数自动依赖注入的方法

它会找出构造函数的参数,再看完整的build方法进行的操作:

public function build($concrete, array $parameters = [])
{
 // If the concrete type is actually a Closure, we will just execute it and
 // hand back the results of the functions, which allows functions to be
 // used as resolvers for more fine-tuned resolution of these objects.
 if ($concrete instanceof Closure) {
  return $concrete($this, $parameters);
 }
 $reflector = new ReflectionClass($concrete);
 // If the type is not instantiable, the developer is attempting to resolve
 // an abstract type such as an Interface of Abstract Class and there is
 // no binding registered for the abstractions so we need to bail out.
 if (! $reflector->isInstantiable()) {
  $message = "Target [$concrete] is not instantiable.";
  throw new BindingResolutionContractException($message);
 }
 $this->buildStack[] = $concrete;
 $constructor = $reflector->getConstructor();
 // If there are no constructors, that means there are no dependencies then
 // we can just resolve the instances of the objects right away, without
 // resolving any other types or dependencies out of these containers.
 if (is_null($constructor)) {
  array_pop($this->buildStack);
  return new $concrete;
 }
 $dependencies = $constructor->getParameters();
 // Once we have all the constructor's parameters we can create each of the
 // dependency instances and then use the reflection instances to make a
 // new instance of this class, injecting the created dependencies in.
 $parameters = $this->keyParametersByArgument(
  $dependencies, $parameters
 );
 $instances = $this->getDependencies(
  $dependencies, $parameters
 );
 array_pop($this->buildStack);
 return $reflector->newInstanceArgs($instances);
}

具体从容器中获取实例的方法:

protected function resolveClass(ReflectionParameter $parameter)
{
 try {
  return $this->make($parameter->getClass()->name);
 }
 // If we can not resolve the class instance, we will check to see if the value
 // is optional, and if it is we will return the optional parameter value as
 // the value of the dependency, similarly to how we do this with scalars.
 catch (BindingResolutionContractException $e) {
  if ($parameter->isOptional()) {
   return $parameter->getDefaultValue();
  }
  throw $e;
 }
}

框架底层通过Reflection反射为开发节省了很多细节,实现了自动依赖注入。这里不做继续深入研究了。

写了一个模拟这个过程的类测试:

<?php
class kulou
{
 //
}
class junjun
{
 //
}
class tanteng
{
 private $kulou;
 private $junjun;
 public function __construct(kulou $kulou,junjun $junjun)
 {
  $this->kulou = $kulou;
  $this->junjun = $junjun;
 }
}
//$tanteng = new tanteng(new kulou(),new junjun());
$reflector = new ReflectionClass('tanteng');
$constructor = $reflector->getConstructor();
$dependencies = $constructor->getParameters();
print_r($dependencies);exit;

原理是通过ReflectionClass类解析类的构造函数,并且取出构造函数的参数,从而判断依赖关系,从容器中取,并自动注入。

转自:小谈博客 http://www.tantengvip.com/2016/01/laravel-construct-ioc/

希望本文所述对大家基于Laravel框架的PHP程序设计有所帮助。

PHP 相关文章推荐
删除数组元素实用的PHP数组函数
Aug 18 PHP
关于file_get_contents返回为空或函数不可用的解决方案
Jun 24 PHP
php中simplexml_load_string使用实例分享
Feb 13 PHP
浅谈PDO的rowCount函数
Jun 18 PHP
详解Laravel视图间共享数据与视图Composer
Aug 04 PHP
PHP数组编码gbk与utf8互相转换的两种方法
Sep 01 PHP
PHP实现活动人选抽奖功能
Apr 19 PHP
php使用str_replace替换多维数组的实现方法分析
Jun 15 PHP
PHP调用API接口实现天气查询功能的示例
Sep 21 PHP
PDO::query讲解
Jan 29 PHP
浅谈PHP无限极分类原理
Mar 14 PHP
如何在Mac上通过docker配置PHP开发环境
May 29 PHP
PHP 二维数组和三维数组的过滤
Mar 16 #PHP
详解php中反射的应用
Mar 15 #PHP
php实现图片上传并进行替换操作
Mar 15 #PHP
php模板引擎技术简单实现
Mar 15 #PHP
9个比较实用的php代码片段
Mar 15 #PHP
Laravel使用Caching缓存数据减轻数据库查询压力的方法
Mar 15 #PHP
php图片添加文字水印实现代码
Mar 15 #PHP
You might like
eWebEditor v3.8 商业完整版 (PHP)
2006/12/06 PHP
php preg_filter执行一个正则表达式搜索和替换
2012/02/27 PHP
web站点获取用户IP的安全方法 HTTP_X_FORWARDED_FOR检验
2013/06/01 PHP
深入密码加salt原理的分析
2013/06/06 PHP
PHP按行读取、处理较大CSV文件的代码实例
2014/04/09 PHP
PHP序列化/对象注入漏洞分析
2016/04/18 PHP
Django中通过定时任务触发页面静态化的处理方式
2018/08/29 PHP
JS判断当前日期是否大于某个日期的实现代码
2012/09/02 Javascript
js 得到文件后缀(通过正则实现)
2013/07/08 Javascript
js浮点数保留两位小数点示例代码(四舍五入)
2013/12/26 Javascript
浅析基于WEB前端页面的页面内容搜索的实现思路
2014/06/10 Javascript
jQuery实现瀑布流的取巧做法分享
2015/01/12 Javascript
浅谈JS原型对象和原型链
2016/03/02 Javascript
js实现楼层导航功能
2017/02/23 Javascript
jQuery实现的手动拖动控制进度条效果示例【测试可用】
2018/04/18 jQuery
微信小程序动态生成二维码的实现代码
2018/07/25 Javascript
json数据传到前台并解析展示成列表的方法
2018/08/06 Javascript
angular中两种表单的区别(响应式和模板驱动表单)
2018/12/06 Javascript
解决vue bus.$emit触发第一次$on监听不到问题
2020/07/28 Javascript
vue实现禁止浏览器记住密码功能的示例代码
2021/02/03 Vue.js
用Python实现一个简单的能够发送带附件的邮件程序的教程
2015/04/08 Python
python实现发送邮件功能
2017/07/22 Python
Django model序列化为json的方法示例
2018/10/16 Python
Python比较配置文件的方法实例详解
2019/06/06 Python
Python过滤掉numpy.array中非nan数据实例
2020/06/08 Python
TensorFlow的环境配置与安装教程详解(win10+GeForce GTX1060+CUDA 9.0+cuDNN7.3+tensorflow-gpu 1.12.0+python3.5.5)
2020/06/22 Python
使用CSS3的font-face字体嵌入样式的方法讲解
2016/05/13 HTML / CSS
日本最大的旅游网站:Rakuten Travel(乐天旅游)
2018/08/02 全球购物
美国杰西潘尼官网:JCPenney
2019/06/12 全球购物
遇到的Mysql的面试题
2014/06/29 面试题
办公室文员工作自我评价
2013/12/01 职场文书
英语自荐信范文
2013/12/11 职场文书
乡镇党的群众路线教育实践活动个人对照检查材料
2014/09/23 职场文书
综合素质评价个性发展自我评价
2015/03/06 职场文书
七年级作文之游记
2019/12/11 职场文书
Golang中interface{}转为数组的操作
2021/04/30 Golang