模型映射器,抽象公共代码的最佳方式是什么,例如,帮助器、装饰器


Model Mapper, what is the best way to abstract common code, i.e. helpers, decorators

使用Zend(1或2),在模型映射器中抽象公共代码的最佳方法是什么?在控制器/视图中有相关的帮助器,那么在映射器中呢…

我倾向于基于两个例子来创建我的映射器:

  1. 《survival the Deep End》作者:Padraic Brady
  2. Dasprid的博客来源

Padraic允许每个映射器组合其他映射器,保持代码DRY,并将每个映射器精确地集中在它需要知道的那些数据库字段上。

Dasprid's使用一个基映射器类来包含处理db连接的通用代码。

在一起,应该有足够的地方来保存公共代码。

当然,Doctrine2 ORM通过配置来管理其中的大部分。经过几次只有一半满意的尝试后,我发现自己对Doctrine更满意了。

只需在库中或存储公共代码的地方创建一个类,例如:

//library/My/Model/Mapper/Abstract.php
<?php
abstract class My_Model_Mapper_Abstract
{
    /**
     * Instance of Zend_Db_Table_Abstract
     *
     * @var Zend_Db_Table_Abstract $tableGateway
     */
    protected $tableGateway = null;
    /**
     * sets up the identity map
     */
    protected $map          = array();
    /**
     * Will accept a DbTable model passed or will instantiate
     * a Zend_Db_Table_Abstract object from table name.
     *
     * @param Zend_Db_Table_Abstract $tableGateway
     */
    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;
        }
    }
    /**
     * Get the default database table adapter.
     *
     * @return Zend_Db_Table_Abstract
     */
    protected function getGateway()
    {
        return $this->tableGateway;
    }
    //truncated for space
    public function findById($id)
    {
        if ($this->getMap($id)) {
            return $this->getMap($id);
        }
        $select = $this->getGateway()->select();
        $select->where('id = ?', $id);
        $row = $this->getGateway()->fetchRow($select);
        $entity = $this->createEntity($row);
        $this->setMap($row->id, $entity);
        return $entity;
    }
    //truncated for space
    /**
     * Abstract method to be implemented by concrete mappers.
     */
    abstract protected function createEntity($row);
}

那么具体的实现可能类似于:

//application/modules/users/model/mappers/User.php
<?php
class Users_Model_Mapper_User extends My_Model_Mapper_Abstract
{
    protected $tableName = 'users';
    public function __construct(Zend_Db_Table_Abstract $tableGateway = null)
    {
        if (is_null($tableGateway)) {
            //TODO: inject this resource
            $tableGateway = new Application_Model_DbTable_User();
        } else {
            $tableGateway = $tableGateway;
        }
        parent::__construct($tableGateway);
    }
    protected function createEntity($row)
    {
        $data = array(
            'id'       => $row->id,
            'username' => $row->username,
            'password' => $row->password
        );
        $user = new Users_Model_User($data);
        return $user;
    }
    private function hashPassword($password)
    {
        return Password::createPasswordHash($password);
    }
    public function saveUser(My_Model_Entity_Abstract $user)
    {
        if (!is_null($user->id)) {
            $select = $this->getGateway()->select();
            $select->where('id = ?', $user->id);
            $row = $this->getGateway()->fetchRow($select);
        } else {
            $row = $this->getGateway()->createRow();
            $row->password = $this->hashPassword($user->password);
        }
        $row->username = $user->username;
        $row->save();
        return $row;
    }
}

这些是为了利用ZF1中常用的DbTable模型而创建的,并且仍在进行中。

ZF2模型可能有些不同,因为ZF2实现和扩展了更多的PHP SPL库,所以一些修改可能是有用的。

祝你好运!

水合器看起来是一个有趣的解决方案http://framework.zend.com/manual/2.2/en/modules/zend.stdlib.hydrator.html