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和AJAX创建RSS聚合器的代码
Mar 13 PHP
php fckeditor 调用的函数
Jun 21 PHP
服务器上配置PHP运行环境教程
Feb 12 PHP
解决更换PHP5.4以上版本后Dedecms后台登录空白问题的方法
Oct 23 PHP
PHP格式化MYSQL返回float类型的方法
Mar 30 PHP
PHP 在数组中搜索给定的简单实例 array_search 函数
Jun 13 PHP
浅谈PHP eval()函数定义和用法
Jun 21 PHP
PHP判断是手机端还是PC端 PHP判断是否是微信浏览器
Mar 15 PHP
php使用curl实现简单模拟提交表单功能
May 15 PHP
thinkPHP框架实现的无限回复评论功能示例
Jun 09 PHP
PHP 7.4 新语法之箭头函数实例详解
May 09 PHP
Yii框架连表查询操作示例
Sep 06 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正则校验用户名介绍
2008/07/19 PHP
PHP获取用户的浏览器与操作系统信息的代码
2012/09/04 PHP
8个必备的PHP功能开发
2015/10/02 PHP
PHP+Redis开发的书签案例实战详解
2019/07/09 PHP
RR vs IO BO3 第一场2.13
2021/03/10 DOTA
js检测客户端不是firefox则提示下载
2007/04/07 Javascript
jquery实现根据浏览器窗口大小自动缩放图片的方法
2015/07/17 Javascript
javascript实现自动输出文本(打字特效)
2015/08/27 Javascript
jQuery使用模式窗口实现在主页面和子页面中互相传值的方法
2016/03/01 Javascript
详解JavaScript for循环中发送AJAX请求问题
2020/06/23 Javascript
javascript中this指向详解
2016/04/23 Javascript
node.js 中国天气预报 简单实现
2016/06/06 Javascript
AngularJS教程 ng-style 指令简单示例
2016/08/03 Javascript
基于JavaScript实现Tab选项卡切换效果
2016/11/24 Javascript
JavaScript自定义函数实现查找两个字符串最长公共子串的方法
2016/11/24 Javascript
JS简单实现表格排序功能示例
2016/12/20 Javascript
在Vue组件中使用 TypeScript的方法
2018/02/28 Javascript
浅谈Vue Element中Select下拉框选取值的问题
2018/03/01 Javascript
中高级前端必须了解的JS中的内存管理(推荐)
2019/07/04 Javascript
Vue看了就会的8个小技巧
2021/01/21 Vue.js
微信小程序组件生命周期的踩坑记录
2021/03/03 Javascript
[11:44]Ti9 OG夺冠时刻
2019/08/25 DOTA
[01:06] DOTA2英雄背景故事第三期之秩序法则光之守卫
2020/07/07 DOTA
Python写的Tkinter程序屏幕居中方法
2015/03/10 Python
python函数局部变量用法实例分析
2015/08/04 Python
Python如何实现守护进程的方法示例
2017/02/08 Python
Python实现删除列表中满足一定条件的元素示例
2017/06/12 Python
python自动化测试之DDT数据驱动的实现代码
2019/07/23 Python
基于Tensorflow读取MNIST数据集时网络超时的解决方式
2020/06/22 Python
Python3爬虫关于识别点触点选验证码的实例讲解
2020/07/30 Python
python实现登录与注册系统
2020/11/30 Python
Melijoe美国官网:法国奢侈童装购物网站
2017/04/19 全球购物
教师反腐倡廉演讲稿
2014/09/03 职场文书
温馨祝福晨语:美丽的一天从我的问候开始
2019/11/28 职场文书
MySQL 可扩展设计的基本原则
2021/05/14 MySQL
使用Python获取字典键对应值的方法
2022/04/26 Python