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模板技术原理【一】
Jan 10 PHP
PHP目录函数实现创建、读取目录教程实例
Jan 13 PHP
php学习笔记 面向对象的构造与析构方法
Jun 13 PHP
初品cakephp 入门基础
Feb 16 PHP
将时间以距今多久的形式表示,PHP,js双版本
Sep 25 PHP
phpcms模块开发之swfupload的使用介绍
Apr 28 PHP
浅析PHP绘图技术
Jul 03 PHP
php实现的获取网站备案信息查询代码(360)
Sep 23 PHP
yii框架通过控制台命令创建定时任务示例
Apr 30 PHP
解读PHP的Yii框架中请求与响应的处理流程
Mar 17 PHP
PHP实现的基于单向链表解决约瑟夫环问题示例
Sep 30 PHP
php设计模式之工厂方法模式分析【星际争霸游戏案例】
Jan 23 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
php csv操作类代码
2009/12/14 PHP
windows服务器中检测PHP SSL是否开启以及开启SSL的方法
2014/04/25 PHP
PHP中empty,isset,is_null用法和区别
2017/02/19 PHP
Laravel Intervention/image图片处理扩展包的安装、使用与可能遇到的坑详解
2017/11/14 PHP
jQuery AJAX 调用WebService实现代码
2010/03/24 Javascript
JavaScript中按位“异或”运算符使用介绍
2014/03/14 Javascript
js控制输入框获得和失去焦点时状态显示的方法
2015/01/30 Javascript
JS表的模拟方法
2015/02/05 Javascript
jQuery实现dialog设置focus焦点的方法
2015/06/10 Javascript
bootstrap读书笔记之CSS组件(上)
2016/10/17 Javascript
深入探究angular2 UI组件之primeNG用法
2017/07/26 Javascript
父组件中vuex方法更新state子组件不能及时更新并渲染的完美解决方法
2018/04/25 Javascript
jquery引入外部CDN 加载失败则引入本地jq库
2018/05/23 jQuery
JavaScript+HTML5 canvas实现放大镜效果完整示例
2019/05/15 Javascript
React路由鉴权的实现方法
2019/09/05 Javascript
js神秘的电报密码 哈弗曼编码实现
2019/09/10 Javascript
python获取当前计算机cpu数量的方法
2015/04/18 Python
微信跳一跳python自动代码解读1.0
2018/01/12 Python
基于Python socket的端口扫描程序实例代码
2018/02/09 Python
python安装requests库的实例代码
2019/06/25 Python
更新pip3与pyttsx3文字语音转换的实现方法
2019/08/08 Python
Python 实现Serial 与STM32J进行串口通讯
2019/12/18 Python
在Tensorflow中实现leakyRelu操作详解(高效)
2020/06/30 Python
Python+Selenium实现自动化的环境搭建的步骤(图文)
2020/09/01 Python
专门经营化妆刷的美国彩妆品牌:Sigma Beauty
2017/09/11 全球购物
爱尔兰电子产品购物网站:Komplett.ie
2018/04/04 全球购物
三星英国官网:Samsung英国
2018/09/25 全球购物
敏捷开发的主要原则都有哪些
2015/04/26 面试题
造价工程师个人求职信
2013/09/21 职场文书
本科生的职业生涯规划范文
2014/01/09 职场文书
小学班主任评语大全
2014/04/23 职场文书
中职生自荐信范文
2014/06/15 职场文书
2015新年联欢晚会开场白
2014/12/14 职场文书
先进个人总结范文
2015/02/15 职场文书
2015年信息化建设工作总结
2015/07/23 职场文书
爱心捐款倡议书:点燃希望,传递温暖
2019/11/04 职场文书