Zend Data Mapper design

I'm using Zend Framework and following the design pattern of separating the Data layer from the Domain layer the problem raises when implementing the methods for the Data mapper so i implemented the save() which insert & update based on whether domain model contains id property and find() which return the records domain object based on id parameter but what if i need to

  • search all/some rows in a table and return all the columns
  • search the same rows and return a mysql COUNT value
  • should i just directly use the class the inherited the Zend_Db_Table_Abstract for these needs or should i implement method for every need ?

    i'm a little confused on how to divide the functionality of the Data Mapper that will fit my needs and my future needs


    You can add individual finder Methods, eg

    class PersonMapper
    {
        … // other code
    
        public function findByLastName()
        {
            // … fetch rowset and map them
        }
    
        public function countByLastName() 
        {
        …
    

    However, that will quickly get out of hand when you need to query multiple columns or want to handle CRUD by arbitrary criteria. You don't want methods like

     public function findByLastNameAndBirthdayAndMaritalStatus()
    

    The easy solution would be to use Zend_Db_Table_Select to create the queries and then pass those to the Data Mapper to execute and map them, eg in your 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
    }
    

    You could abstract this further with the Mapper returning and accepting PersonQueryBuilder instead, which hides the SQL Semantics inside and let's you specify against your Domain Objects instead. It's more effort though.

    Also have a look at the Repository and Specification Pattern.


    As much as Gordon very likely has the correct answer, I find it overly complex for my tastes and needs at the moment.

    I use a base mapper class for all of my domain mappers and I put as much functionality into the base class as I can.

    I use a find by column method that works fairly well in all of my mappers:

    //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;
        }
    

    I hope you find this useful as an idea generator at the least. Also if you wish to implement a SQL Count() statement in a method similar to this it will go easier if you use Zend_Db_Expr() when you build that select().

    链接地址: http://www.djcxy.com/p/56236.html

    上一篇: PHP如何在MVC中实现Data Mapper模式

    下一篇: Zend数据映射器设计