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 和 MySQL 基础教程(二)
Oct 09 PHP
用PHP读取RSS feed的代码
Aug 01 PHP
叫你如何修改Nginx与PHP的文件上传大小限制
Sep 10 PHP
ThinkPHP框架设计及扩展详解
Nov 25 PHP
php+Mysqli利用事务处理转账问题实例
Feb 11 PHP
Codeigniter发送邮件的方法
Mar 19 PHP
PHP中的事务使用实例
May 26 PHP
ThinkPHP框架分布式数据库连接方法详解
Mar 14 PHP
PHP守护进程化在C和PHP环境下的实现
Nov 21 PHP
Laravel多用户认证系统示例详解
Mar 13 PHP
PHP通过GD库实现验证码功能示例
Feb 23 PHP
PHP全局使用Laravel辅助函数dd
Dec 26 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
mysql 性能的检查和优化方法
2009/06/21 PHP
一个PHP并发访问实例代码
2012/09/06 PHP
Yii框架组件和事件行为管理详解
2016/05/20 PHP
Laravel框架源码解析之反射的使用详解
2020/05/14 PHP
JavaScript 异步调用框架 (Part 5 - 链式实现)
2009/08/04 Javascript
利用jQuery操作对象数组的实现代码
2011/04/27 Javascript
javascript 基础篇4 window对象,DOM
2012/03/14 Javascript
轻松创建nodejs服务器(4):路由
2014/12/18 NodeJs
jQuery中Ajax的load方法详解
2015/01/14 Javascript
详解JavaScript中的异常处理方法
2015/06/16 Javascript
微信小程序链接传参并跳转新页面
2016/11/29 Javascript
JS实现图片垂直居中显示小结
2016/12/13 Javascript
详解angularJS自定义指令间的相互交互
2017/07/05 Javascript
vue多种弹框的弹出形式的示例代码
2017/09/18 Javascript
nuxt.js 在middleware(中间件)中实现路由鉴权操作
2020/11/06 Javascript
Python程序员鲜为人知但你应该知道的17个问题
2014/06/04 Python
Python实现多条件筛选目标数据功能【测试可用】
2018/06/13 Python
Python tcp传输代码实例解析
2020/03/18 Python
详解python如何引用包package
2020/06/07 Python
浅谈多卡服务器下隐藏部分 GPU 和 TensorFlow 的显存使用设置
2020/06/30 Python
使用darknet框架的imagenet数据分类预训练操作
2020/07/07 Python
Python3如何实现Win10桌面自动切换
2020/08/11 Python
selenium+python实现基本自动化测试的示例代码
2021/01/27 Python
ANINE BING官方网站:奢华的衣橱基本款和时尚永恒的单品
2019/11/26 全球购物
SQL Server笔试题
2012/01/10 面试题
口头翻译求职人自荐信
2013/12/07 职场文书
群众路线教育实践活动方案
2014/02/02 职场文书
行政人事专员岗位职责
2014/03/05 职场文书
公司管理建议书范文
2014/03/12 职场文书
家长写给孩子的评语
2014/04/18 职场文书
2014年最新离婚协议书范本
2014/10/11 职场文书
医生见习报告范文
2014/11/03 职场文书
文明单位创建材料
2014/12/24 职场文书
英文自荐信范文
2015/03/25 职场文书
乡镇团代会开幕词
2016/03/04 职场文书
委托开发合同书(标准版)
2019/08/07 职场文书