-1

您能否帮助扩展一下Zend 快速入门:在本教程中,我们使用 Mapper 更新单个留言簿。如果我想更新多个留言簿怎么办?并基于某些条件?

例如,我有一个删除所有在 2012 年 12 月 21 日之前创建的留言簿的操作。我应该更新什么来实现这一点?

我的方法有意义吗?

// application/models/GuestbookMapper.php 
class Application_Model_GuestbookMapper
{
    public function deleteByCreatedBefore($date)
    {
        $this->getDbTable()->deleteByCreatedBefore($date);
    }
}

// application/models/DbTable/Guestbook.php 
class Application_Model_DbTable_Guestbook extends Zend_Db_Table_Abstract
{
    public function deleteByCreatedBefore($date) {
        $where = $this->getAdapter()->quoteInto('created < ?', $date);
        $this->delete($where);
    }
}

谢谢,

4

1 回答 1

0

如果您正在使用快速入门模型/映射器并希望忠实于该数据映射器范例,则Application_Model_DbTable_Guestbook除了属性(“名称”、“主”...)之外,您将没有任何东西。DbTable 模型将作为该单个表的数据库适配器存在。

您的删除功能将被放置在映射器中。

class Application_Model_GuestbookMapper
{
    public function deleteByCreatedBefore($date)
    {
        $where = $this->getDbTable()->quoteInto('created < ?', $date);
        //delete() returns num of rows deleted
        $this->getDbTable()->delete($where);
    }
}

这将起作用,但可能不是实现所需功能的最佳/最安全的方法。

数据映射器的这个特殊示例非常简单,可能会误导某些人。映射器的留言簿示例实际上并不能很好地表示映射器,因为数据库行和域模型 (Application_Model_Guestbook) 映射 1 到 1(一个数据库列到一个模型属性)。

当您需要将多个数据库表映射到单个域模型时,数据映射器开始大放异彩。每次调用 delete() 时,您的域模型 (Application_Model_Guestbook) 可能必须影响一个以上的数据库表,因此 delete() 函数的结构很重要。

你应该怎么做才能使用映射器完成删除?

第一:更新Application_Model_GuestbookMapper::fetchAll()接受一个$where参数,我通常设置这种类型的函数来接受一个设置列和值的数组。

//accepted parameters: Zend_Db_Table::fetchAll($where = null, $order = null, $count = null, $offset = null)
//accepts array (column => value )
public function fetchAll(array $where = null)
    {
        $select = $this->getDbTable()->select();
        if (!is_null($where) && is_array($where)) {
            //using a column that is not an index may effect database performance
            $select->where($where['column'] = ?, $where['value']);
        } 
        $resultSet = $this->getDbTable()->fetchAll($select);
        $entries   = array();
        foreach ($resultSet as $row) {
            $entry = new Application_Model_Guestbook();
            $entry->setId($row->id)
                  ->setEmail($row->email)
                  ->setComment($row->comment)
                  ->setCreated($row->created);
            $entries[] = $entry;
        }
        return $entries;
    }

第二:重构您Application_Model_GuestbookMapper::deleteByCreatedBefore()以接受来自的输出fetchAll()(实际上,构建一个接受输出的 delete() 函数会更简单:Guestbook 对象数组)

 //accepts an array of guestbook objects or a single guestbook object
 public function deleteGuestbook($guest)
    {
        if (is_array($guest) {
            foreach ($guest as $book) {
                if ($book instanceof Application_Model_Guest){
                    $where = $this->getDbTable()->quoteInto('id = ?', $book->id);
                    $this->getDbTable()->delete($where);
                }
            }
        } elseif ($guest instanceof Application_Model_Guest) {
            $where = $this->getDbTable()->quoteInto('id = ?', $guest->id);
                    $this->getDbTable()->delete($where);
        } else {
            throw new Exception;
        }
    }

将域对象作为对象删除将变得更加重要,因为您必须考虑删除对象将如何影响其他对象或持久性(数据库)范例。在某些时候,您会遇到一种情况,如果其他对象仍然存在,您不希望删除成功。

这只是一个意见,但我希望它有所帮助。

于 2012-12-26T11:23:12.063 回答