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+.htaccess实现全站静态HTML文件GZIP压缩传输(一)
Feb 15 PHP
php获取当前网址url并替换参数或网址的方法
Jun 06 PHP
php中使用Curl、socket、file_get_contents三种方法POST提交数据
Aug 12 PHP
使用php计算排列组合的方法
Nov 13 PHP
PHP实现抓取HTTPS内容
Dec 01 PHP
php使用数组填充下拉列表框的方法
Mar 31 PHP
WordPress中用于检索模版的相关PHP函数使用解析
Dec 15 PHP
深入理解PHP类的自动载入机制
Sep 16 PHP
PHP实现文件上传下载实例
Oct 18 PHP
php文件上传 你真的掌握了吗
Nov 28 PHP
php实现评论回复删除功能
May 23 PHP
深入理解PHP+Mysql分布式事务与解决方案
Dec 03 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 面向对象之成员方法详解
2013/05/04 PHP
ThinkPHP控制器里javascript代码不能执行的解决方法
2014/11/22 PHP
smarty模板引擎中自定义函数的方法
2015/01/22 PHP
php写入、删除与复制文件的方法
2015/06/20 PHP
UTF-8正则表达式如何匹配汉字
2015/08/03 PHP
PHP+AJAX实现投票功能的方法
2015/09/28 PHP
PHP安全之register_globals的on和off的区别
2020/07/23 PHP
P3P Header解决Cookie跨域的问题
2013/03/12 Javascript
jquery阻止后续事件只执行第一个事件
2014/07/24 Javascript
JavaScript闭包函数访问外部变量的方法
2014/08/27 Javascript
调试JavaScript中正则表达式中遇到的问题
2015/01/27 Javascript
jQuery 判断图片是否加载完成方法汇总
2015/08/10 Javascript
javascript实现显示和隐藏div方法汇总
2015/08/14 Javascript
JSON与String互转的实现方法(Javascript)
2016/09/27 Javascript
原生js实现淘宝购物车功能
2020/06/23 Javascript
JavaScript基本类型值-Number类型
2017/02/24 Javascript
通过npm引用的vue组件使用详解
2017/03/02 Javascript
js 获取今天以及过去日期
2017/04/11 Javascript
Vue学习笔记之表单输入控件绑定
2017/09/05 Javascript
vue之延时刷新实例
2019/11/14 Javascript
JS实现字体背景跑马灯
2020/01/06 Javascript
在Python中操作文件之truncate()方法的使用教程
2015/05/25 Python
解决Python中字符串和数字拼接报错的方法
2016/10/23 Python
django中的HTML控件及参数传递方法
2018/03/20 Python
浅谈Django+Gunicorn+Nginx部署之路
2019/09/11 Python
python生成requirements.txt的两种方法
2019/09/18 Python
英国网上香水店:Fragrance Direct
2016/07/20 全球购物
Backcountry旗下的户外商品闪购网站:steep&cheap
2016/09/22 全球购物
英国巧克力贸易公司:Chocolate Trading Company
2017/03/21 全球购物
加拿大领先的时尚和体育零售商:Sporting Life
2019/12/15 全球购物
美国在线和移动免费会员制批发零售商:Boxed(移动端的Costco)
2020/01/02 全球购物
三分钟自我介绍演讲稿
2014/08/21 职场文书
避暑山庄导游词
2015/02/04 职场文书
入党介绍人考察意见
2015/06/01 职场文书
廉洁自律承诺书2016
2016/03/25 职场文书
Django实现在线无水印抖音视频下载(附源码及地址)
2021/05/06 Python