首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何设计领域层对象来表示Zend框架中的多个对象和单个对象?

如何设计领域层对象来表示Zend框架中的多个对象和单个对象?
EN

Stack Overflow用户
提问于 2008-12-17 00:09:29
回答 1查看 1.2K关注 0票数 6

我正致力于在Zend Framework中创建一个独立于数据访问层的域层。数据访问层由两个主要对象组成,一个表数据网关和一个行数据网关。根据Bill Karwin对this earlier question的回复,我现在有以下代码用于我的域Person对象:

代码语言:javascript
复制
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)
    {

    }
}

但是,这只适用于单个行。我还需要创建一个域对象,它可以表示整个表,并且(假设)可以用来迭代表中的所有person,并返回适当类型的person (admin、buyer等)对象以供使用。基本上,我的设想如下:

代码语言:javascript
复制
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;
        }
    }
}

这是处理这个特殊问题的好方法还是坏方法?我应该对整体设计进行哪些改进或调整?

提前感谢您的评论和批评。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2008-12-17 01:33:25

我认为您将使用Domain Model类来完全隐藏您正在使用数据库表进行持久化的事实。因此,传递Table对象或Row对象应该完全在幕后进行:

代码语言:javascript
复制
<?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使得编写单元测试代码变得困难,而且它还有一些与静态和子类化相关的恼人的缺陷。但是,正如我们在这段代码中看到的那样,它也有一些优点。您必须根据具体情况来判断自己是否利大于弊。

“Zend Framework会支持Finder类吗?”

我不认为这是必要的。

“在模型类中将find方法重命名为get是否有特殊的原因?”

为了区别于find(),我将该方法命名为get()。"getter“范例与OO接口相关,而”finder“传统上与数据库相关。我们正在尝试设计域模型,以假装不涉及数据库。

“您会继续使用相同的逻辑来实现特定的getBy和getCollectionBy方法吗?”

我拒绝创建泛型getBy()方法,因为它很容易让它接受泛型SQL表达式,然后将其逐字传递给数据访问对象。这将我们的域模型的使用与底层数据库表示联系起来。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/373244

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档