Zend 框架中如何设计领域层对象来表示多个对象和单个对象?
Posted
技术标签:
【中文标题】Zend 框架中如何设计领域层对象来表示多个对象和单个对象?【英文标题】:How to Design Domain Layer Objects to Represent Multiple Objects & Single Object in Zend Framework? 【发布时间】:2008-12-17 00:09:29 【问题描述】:我正致力于在 Zend Framework 中创建一个与数据访问层分开的域层。数据访问层由两个主要对象组成,一个表数据网关和一个行数据网关。根据 Bill Karwin 对 this earlier question 的回复,我的域 Person 对象现在有了以下代码:
class Model_Row_Person
protected $_gateway;
public function __construct(Zend_Db_Table_Row $gateway)
$this->_gateway = $gateway;
public function login($userName, $password)
public function setPassword($password)
但是,这仅适用于单个行。我还需要创建一个可以表示整个表的域对象,并且(可能)可以用来遍历表中的所有人员并返回适当类型的人员(管理员、买家等)对象以供使用。基本上,我设想如下:
class Model_Table_Person implements SeekableIterator, Countable, ArrayAccess
protected $_gateway;
public function __construct(Model_DbTable_Person $gateway)
$this->_gateway = $gateway;
public function current()
$current = $this->_gateway->fetchRow($this->_pointer);
return $this->_getUser($current);
private function _getUser(Zend_Db_Table_Row $current)
switch($current->userType)
case 'admin':
return new Model_Row_Administrator($current);
break;
case 'associate':
return new Model_Row_Associate($current);
break;
这是处理这个特定问题的好方法还是坏方法?我应该对整体设计进行哪些改进或调整?
提前感谢您的 cmets 和批评。
【问题讨论】:
【参考方案1】:我曾想过,您将使用域模型类来完全隐藏您使用数据库表进行持久性这一事实。所以传递一个 Table 对象或一个 Row 对象应该完全在幕后:
<?php
require_once 'Zend/Loader.php';
Zend_Loader::registerAutoload();
$db = Zend_Db::factory('mysqli', array('dbname'=>'test',
'username'=>'root', 'password'=>'xxxx'));
Zend_Db_Table_Abstract::setDefaultAdapter($db);
class Table_Person extends Zend_Db_Table_Abstract
protected $_name = 'person';
class Model_Person
/** @var Zend_Db_Table */
protected static $table = null;
/** @var Zend_Db_Table_Row */
protected $person;
public static function init()
if (self::$table == null)
self::$table = new Table_Person();
protected static function factory(Zend_Db_Table_Row $personRow)
$personClass = 'Model_Person_' . ucfirst($personRow->person_type);
return new $personClass($personRow);
public static function get($id)
self::init();
$personRow = self::$table->find($id)->current();
return self::factory($personRow);
public static function getCollection()
self::init();
$personRowset = self::$table->fetchAll();
$personArray = array();
foreach ($personRowset as $person)
$personArray[] = self::factory($person);
return $personArray;
// protected constructor can only be called from this class, e.g. factory()
protected function __construct(Zend_Db_Table_Row $personRow)
$this->person = $personRow;
public function login($password)
if ($this->person->password_hash ==
hash('sha256', $this->person->password_salt . $password))
return true;
else
return false;
public function setPassword($newPassword)
$this->person->password_hash = hash('sha256',
$this->person->password_salt . $newPassword);
$this->person->save();
class Model_Person_Admin extends Model_Person
class Model_Person_Associate extends Model_Person
$person = Model_Person::get(1);
print "Got object of type ".get_class($person)."\n";
$person->setPassword('potrzebie');
$people = Model_Person::getCollection();
print "Got ".count($people)." people objects:\n";
foreach ($people as $i => $person)
print "\t$i: ".get_class($person)."\n";
“我认为静态方法不好 这就是我试图创造的原因 表级方法作为实例 方法。”
我不接受任何笼统的说法,即static
总是不好,或者单身总是不好,或者goto
总是不好,或者你有什么。做出如此明确声明的人正在寻求过度简化问题。适当使用语言工具,它们会对你有好处。
也就是说,当您选择一种语言结构时,通常需要进行权衡,它使某些事情变得更容易,而其他事情变得更难。人们经常指出static
使编写单元测试代码变得困难,而且PHP 在静态和子类化方面也存在一些令人讨厌的缺陷。但也有一些优势,正如我们在这段代码中看到的那样。您必须根据具体情况自行判断利大于弊。
“Zend 框架是否支持 Finder 上课?”
我认为没有必要。
“你有什么特别的原因吗? 重命名要进入的查找方法 模型类?”
我将方法命名为get()
只是为了区别于find()
。 “getter”范式与 OO 接口相关联,而“finders”传统上与数据库相关联。我们正在尝试设计域模型以假装不涉及数据库。
“你会使用继续使用 实现特定 getBy 的相同逻辑 和 getCollectionBy 方法?”
我拒绝创建一个通用的getBy()
方法,因为它很容易接受一个通用的SQL 表达式,然后将它逐字传递给数据访问对象。这将我们的领域模型的使用与底层数据库表示相结合。
【讨论】:
顺便说一句,我以此作为练习来学习如何在新的 NetBeans 6.5 中编写 PHP。它摇滚! 两个问题:1)我认为静态方法不好,这就是为什么我试图将表级方法创建为实例方法。 Zend Framework 会支持 Finder 类吗? 2) 您是否有特殊原因将 find 方法重命名为在模型类中获取?并且您会继续使用相同的逻辑来实现特定的 getBy 和 getCollectionBy 方法吗? 我猜这真的是三个问题:-) 非常感谢您的回复。为了澄清最后的问题,我正在考虑做相反的事情,例如,我将要构建一个函数 getCollectionByUserType('admin') 或 getByUserName('albus')。为每个用例创建一个静态方法是否有问题?以上是关于Zend 框架中如何设计领域层对象来表示多个对象和单个对象?的主要内容,如果未能解决你的问题,请参考以下文章