Zend框架 - 为什么我应该使用数据映射器/Db_Table_Row?

扩展问题:为什么我应该使用数据映射器/Db_Table_Row,因为DbTable能够处理数据操作的大多数基本任务。

我目前正在学习采埃孚 v1.11

对于数据库操作,我为每个表创建了 DbTable。例如,“users”表由Application_Model_DbTable_Users表示,其中没有其他代码。

操作数据时,我可以使用:

<?php
$uTable = new Application_Model_DbTable_Users();
$newUid = $uTable->insert(array('name'=>'Old Name', 'email'=>''));
$user = $uTable->find($newUid)->current();

// Then I can use $user which is instance of Table_Row
$user->name = "New Name";
$user->email = "email@addr.com";
$user->save();

我的问题是,我什么时候需要定义一个行类(假设Table_Row在ZF教程中被称为DataMapper)

// By, adding this to the DbTable class
protected $_rowClass = 'Application_Model_User';

为每个实体设置一个 Row 类有什么好处?任何人都可以向我指出这方面的最佳实践。


答案 1

您不需要定义自己的Table_Row。但是,在许多情况下,它可能很有用,特别是如果要为给定的用户行定义一些特定方法或属性。它们还可以提高代码的可读性。

例如,在 Users 表案例中,可以在自定义用户行中定义一个名为 getFullName() 的方法::

public function getFullName() {
    return $this->firstName . ' ' . $this->lastName;
}

然后,当您获取用户行对象时,要获取用户的全名,您只需执行以下操作:

$user = $uTable->find($newUid)->current();
$fullName = $user->getFullName();

第二个示例是“用户”表的某些父表,如“地址”。在这种情况下,您可以在用户行中定义一个名为 getAddress 的方法:

public function getAddress() {
    return $this->findParentRow('Application_Model_DbTable_Addresses');
}

在这种情况下,您将获得当前用户的地址行对象,如下所示..

$user = $uTable->find($newUid)->current();
$addressRow = $user->getAddress();

另一个示例是当您想要创建自定义删除或 instert 方法时。假设您要确保不想使用 delete() 方法删除管理员用户。然后,您可以从Zend_Db_Table_Row重载删除方法,如下所示:

public function delete() {
        if ('admin' === $this->userRole) {
              return 0;
        }
        return parent::delete();
} 

这样,您就无法仅通过对用户行对象调用 delete() 来删除管理员用户:

 $user = $uTable->find($newUid)->current();
 $rowsDeleted = $user->delete(); // would be 0 if $user is admin

这些只是三个基本示例,显示了定义自己的行类的有用性。但是,它们当然不是必需的。但是,根据我自己的经验,它们非常方便。


答案 2

简而言之:这是关于隔离的。

Zend_Db_Table是表数据网关的实现。它通过一个类将 CRUD 访问引导到特定的表视图。它通常与表模块一起使用,例如,包含网关处理的记录的业务逻辑的类。

Zend_Db_Table_Row行数据网关模式的实现。在这里,返回的对象看起来与数据库记录完全相同,并且它们包含处理该数据的业务逻辑,但它们不包含CRUD与它们来自的表的逻辑(这将是ActiveRecord),而是聚合它们。

行数据网关很好,只要没有太多的对象关系阻抗不匹配即可。对象在关系数据库中的持久化方式以及它在对象世界中的外观通常是完全不同的事情。使用域模型时,业务对象的结构通常与存储在数据库中的方式不同。因此,您无法轻松地从数据库中对它们进行 CRUD 处理。这就是DataMapper发挥作用的地方。

数据映射器负责将域对象映射到记录集,反之亦然。这使您的应用程序更易于维护,因为它将 Domain 对象与数据库结构分离。它使它们保持分离,并在如何对两个层(持久性和域)进行建模方面为您提供了更大的灵活性。


推荐