使用Zend(1或2),在模型映射器中抽象公共代码的最佳方法是什么?在控制器/视图中有相关的帮助器,那么在映射器中呢…
我倾向于基于两个例子来创建我的映射器:
- 《survival the Deep End》作者:Padraic Brady
- 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