1

我正在使用 Zend 框架并遵循将数据层与域层分离的设计模式,在实现数据映射器的方法时会出现问题,因此我save()根据域模型是否包含 id 属性和find()返回值来实现插入和更新基于 id 参数的记录域对象但是如果我需要怎么办

  1. 搜索表中的所有/某些行并返回所有列
  2. 搜索相同的行并返回一个 mysql COUNT 值

我应该直接使用继承 Zend_Db_Table_Abstract 的类来满足这些需求,还是应该为每个需求实现方法?

我对如何划分适合我的需求和未来需求的数据映射器的功能有点困惑

4

2 回答 2

2

您可以添加单独的查找器方法,例如

class PersonMapper
{
    … // other code

    public function findByLastName()
    {
        // … fetch rowset and map them
    }

    public function countByLastName() 
    {
    …

但是,当您需要查询多个列或想要通过任意条件处理 CRUD 时,这将很快失控。你不想要像这样的方法

 public function findByLastNameAndBirthdayAndMaritalStatus()

简单的解决方案是使用Zend_Db_Table_Select创建查询,然后将它们传递给 Data Mapper 以执行和映射它们,例如在您的 DataMapper

public function getSelect()
{
    return $this->personTable->select();
}

public function findBy(Zend_Db_Table_Select $select)
{
    $people = $this->personTable->fetchAll($select);
    // map people to People objects
}

您可以使用 Mapper 返回并接受 PersonQueryBuilder 来进一步抽象这一点,这会将 SQL 语义隐藏在里面,让您改为针对您的域对象进行指定。不过还是比较费力。

还可以查看存储库和规范模式。

于 2012-10-10T18:52:31.870 回答
0

尽管 Gordon 很可能有正确的答案,但我发现它目前对我的品味和需求来说过于复杂。

我为我的所有域映射器使用了一个基映射器类,并且我将尽可能多的功能放入基类中。

我使用按列查找的方法,该方法在我的所有映射器中都运行良好:

//from abstract class Model_Mapper_Abstract

//The constructor of my base class accepts either a dbtable model
// or the name of a table stored in the concrete mapper tablename property. 
 public function __construct(Zend_Db_Table_Abstract $tableGateway = null)
    {   
        if (is_null($tableGateway)) {   
            $this->tableGateway = new Zend_Db_Table($this->tableName);
        } else {    
            $this->tableGateway = $tableGateway;
        }
    }
/**
 * findByColumn() returns an array of entity objects
 * filtered by column name and column value.
 * Optional orderBy value.
 *
 * @param string $column
 * @param string $value
 * @param string $order optional
 * @return array of entity objects
 */
public function findByColumn($column, $value, $order = null)
    {
        //create select object
        $select = $this->getGateway()->select();
        $select->where("$column = ?", $value);
        //handle order option
        if (!is_null($order)) {
            $select->order($order);
        }
        //get result set from DB
        $result = $this->getGateway()->fetchAll($select);
        //turn DB result into domain objects (entity objects)
        $entities = array();
        foreach ($result as $row) {
            //create entity, handled by concrete mapper classes
            $entity = $this->createEntity($row);
            //assign this entity to identity map for reuse if needed
            $this->setMap($row->id, $entity);
            $entities[] = $entity;
        }
        //return an array of entity objects
        return $entities;
    }

我希望你觉得这至少作为一个想法生成器很有用。此外,如果您希望在与此类似的方法中实现语句,则在构建 select( ) 时使用 Zend_Db_Expr()SQL Count()会更容易。

于 2012-10-11T10:16:09.333 回答