8

我们刚刚开始齐心协力在我们的项目中统一使用依赖注入,我遇到了一个问题。

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

特别是,我们有一个 MongoCollection 方法的包装器 findOne,如果您传入一个字符串,当前(在旧代码中)将该字符串转换为带有“new MongoId($_id)”的 MongoId,并将其用于查找功能。

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

但是,当 MongoId 类在构造函数上获取 id 字符串时,我该如何处理注入呢?

我认为唯一可行的方法是在类构造函数上传递一个闭包,该闭包执行以下操作:

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

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

[编辑以修复最后一部分]

但这是正确的处理方式吗?当然,如果我们使用 DiC,我们可以做到,但是要求构造函数的闭包似乎有点多。我对注入我的依赖关系太教条了吗?我想我可以通过在新类中使用“new MongoId($_id)”来轻松解决这个问题。

4

2 回答 2

2

您可以使用工厂代替闭包:

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

在工厂中,拥有“新事物”硬编码依赖项被认为是可以的,因为创建对象是它们的唯一目的,您可以轻松地将它们替换为另一个工厂。

MyMongoMongoFactory的消费者类(

于 2013-01-21T22:14:02.830 回答
1

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

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

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

它会(在 PHPUnit 中)吗?

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

但是,当 MongoId 类在构造函数上获取 id 字符串时,我该如何处理注入呢?

不知道你的意思是什么,但你应该只测试MongoIds 处理的结果。

你问题的最后一点让我有点松懈,我认为这是因为它不是真正的 PHP(即$__construct)。

我不确定你为什么需要像这样将函数推入类中。我的意思是我最多的时候是:

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

你不需要更多的东西,你不需要测试构造函数,MongoId因为它已经过单元测试,你应该对你的公共 API 而不是其他人的公共 API 进行单元测试。

于 2013-01-21T21:48:27.113 回答