通过数据映射器处理集合模式中的项


Handling items in the collection pattern by a data mapper

我的问题与@tereško的回答"谁应该处理复杂查询中的条件,数据映射器还是服务层?"中的更新部分有关。以下是供参考和方便的代码。

$category = new Category;
$category->setTitle( 'privacy' );
$list = new ArticleCollection;
$list->setCondition( $category );
$list->setDateRange( mktime( 0, 0, 0, 12, 9, 2001) );
// it would make sense, if unset second value for range of dates 
// would default to NOW() in mapper
$mapper = new ArticleCollectionMapper;
$mapper->fetch( $list );
foreach ( $list as $article )
{
    $article->setFlag( Article::STATUS_REMOVED );
}
$mapper->store( $list );

在此代码中,ArticleCollection是域对象的集合,我们称它们为Article s。当ArticleCollectionMapper从数据库中获取数据并将其分配给$list时,需要创建Article的实例(对于每一行)。Article的实例会通过像$list->addArticle($newArticle)这样的方法添加到我们的集合实例($list)中吗?应该使用像ArticleFactory这样的工厂对象,还是有另一个我没有考虑过的选项?

我不认为实际使用工厂对象来添加文章。不过,您可能会看到自己使用一个实例来创建Article的实例(在第二个示例中)。我接下来所做的是向ArticleCollection实例添加一个addArticles ()方法。通过这种方式,您可以简单地从映射器调用ArticleCollection实例上的方法。ArticleCollectionMapper可能看起来像:

class ArticleCollectionMapper extends DataMapperAbstract
{
    public function fetch ( ArticleCollection $articles )
    {
        $prepare = $this->connection->prepare( "SELECT ..." );
        $prepare->execute();
        // filter conditions
        $articles->addArticles( $prepare->fetchAll() );
    }
}

您需要通过从ArticleCollection实例获取条件来进行一些过滤,这在上面的代码片段中被排除了。那么我们的域对象的addArticles()实现将类似于以下内容:

class ArticleCollection extends DomainObjectAbstract
{
    protected $collection = array();
    public function addArticles ( Array $articles )
    {
        foreach ( $articles as $article )
        {
            $articleCollectionItem = new Article;
            $articleCollectionItem->setParams( $article );
            // however you prefer filling your list with `Article` instances
            $this->collection[] = $articleCollectionItem;
        }
    }
}

你可能还想根据你的需要添加一个addArticle()方法,然后用对addArticle()的调用替换上面foreach中的内容。注意,上面的例子是非常简化的,代码需要调整以满足您的标准。