当构造函数的参数不可用时注入依赖项


PHP Dependency injection when the arguments for the constructor are not available

我们刚刚开始努力在项目中统一使用依赖注入,但是我遇到了一个问题。

我正在写一个类来处理我们的MongoDB查询。我传入一个MongoClient作为构造函数的依赖项,没有问题。但是,当实例化对象所需的变量在实例化时不可用时,我该如何处理依赖关系呢?

特别是,我们有一个包装的蒙古收集方法,findOne,那,如果你传入一个字符串,目前(在旧代码)将该字符串转换成一个蒙古id与"新蒙古id ($_id)",并使用它的查找函数。

根据我对依赖注入的了解,拥有"new MongoId"是一个坏主意,而且我已经知道,它将使为将字符串转换为MongoId的函数编写测试用例变得更加困难。

但是,当MongoId类在构造函数中使用id字符串时,我如何处理注入呢?

我想到的唯一可行的方法是在类构造函数上传递一个闭包,它的作用如下:

$getMongoId = function( $id ){
    return new MongoId( $id );
};

class MyMongo
{
   function __construct( MongoClient $client, Closure $mongoIdGetter){...}
}

但是这是正确的处理方法吗?当然,如果我们使用DiC的话,我们可以这样做,但是要求构造函数使用闭包似乎有点过分了。在注入依赖项方面,我是不是太教条了?我可以很容易地通过在新类中使用"new MongoId($_id)"来解决这个问题,我想。

可以使用Factory来代替闭包:

class MongoFactory
{
    public function createMongoDb($id)
    {
        return new MongoId($id);
    }
}

在工厂中,有"新东西"的硬编码依赖被认为是可以的,因为对象的创建是它们的唯一目的,你可以很容易地用另一个工厂替换它们。

你的消费者类(MyMongo)现在将依赖于MongoFactory(或者它的接口,如果你愿意的话),你可以很容易地"注入"。

但是,当实例化对象所需的变量在实例化时不可用时,我如何处理依赖关系?

PHP会在你有机会自己处理之前发生致命错误。如果你使用类型参数和/或不定义它们,默认情况下,null PHP将致命错误,当该参数没有传递给任何函数。

根据我对依赖注入的了解,拥有"new MongoId"是一个坏主意,而且我已经知道,它将使为将字符串转换为MongoId的函数编写测试用例变得更加困难。

Will it(在PHPUnit中)?

$this->assertInstanceOf(''MongoId', $getMongoId($id_string));

但是,当MongoId类在构造函数中使用id字符串时,我如何处理注入呢?

不知道这是什么意思,但是您应该只测试MongoId s处理的结果。

你的问题的最后一点失去了我一点,我认为这是因为它不是真正的PHP(即$__construct)。

我不确定为什么你需要像那样把函数塞进类中。我的意思是,我大多数时候都是:

function findById($id){
    if(!$id instanceof 'MongoId) $id = new MongoId($id);
    return $this->getCollection()->findOne($id);
}

你不需要更多的东西,你不需要测试MongoId的构造函数,因为它已经经过了单元测试,你应该代替单元测试你的公共API,而不是别人的