Php Zend framework-为什么要使用数据映射器/Db\u Table\u行?

Php Zend framework-为什么要使用数据映射器/Db\u Table\u行?,php,database,design-patterns,zend-framework,zend-db-table,Php,Database,Design Patterns,Zend Framework,Zend Db Table,扩展问题:为什么要使用data mapper/Db\u Table\u行,因为as DbTable能够处理大多数数据操作的基本任务。 我目前正在学习ZF v1.11 对于数据库操作,我为每个表创建了DbTable。例如,“用户”表由应用程序\模型\数据库\用户表示,其中不包含其他代码 在处理数据时,我可以使用: <?php $uTable = new Application_Model_DbTable_Users(); $newUid = $uTable->insert(array(

扩展问题:为什么要使用data mapper/Db\u Table\u行,因为as DbTable能够处理大多数数据操作的基本任务。

我目前正在学习ZF v1.11

对于数据库操作,我为每个表创建了DbTable。例如,“用户”表由应用程序\模型\数据库\用户表示,其中不包含其他代码

在处理数据时,我可以使用:

<?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();

为每个实体创建一个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();
public function delete() {
        if ('admin' === $this->userRole) {
              return 0;
        }
        return parent::delete();
} 
另一个例子是当您想要创建自定义的delete或insert方法时。假设您希望确保不希望使用delete()方法删除管理员用户。然后您可以从Zend_Db_Table_行重载delete方法,如下所示:

$user = $uTable->find($newUid)->current();
$addressRow = $user->getAddress();
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

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

简而言之:这是关于隔离

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

Zend_Db_Table_Row
是的一个实现。在这里,返回的对象看起来完全像一个数据库记录,它们包含处理该数据的业务逻辑,但是它们不包含对它们来自的表进行CRUD的逻辑(这将是一个ActiveRecord),而是对它们进行聚合

行数据网关是好的,只要您没有太多。对象在关系数据库中的持久化方式和在对象世界中的外观通常是完全不同的。使用时,业务对象的结构通常与存储在数据库中的方式不同。因此,您无法轻松地从数据库中对它们进行CRUD。这就是发挥作用的地方


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

-给出了一个想法,即发送电子邮件或更改密码逻辑可以在表行类中实现,这是特定于用户的。在问题373054的答案中,有一个函数sendMailTo用于用户,在Db_Row类中保留与数据库无关的函数是一种好的做法吗?这些特定于用户的业务逻辑应该停留在哪里?@Hossain Khan。事实上,Bill Karwin介绍的是您自己的类Person,它包含与个人相关的业务逻辑。请注意,Person类不扩展任何类。该类的构造函数可能会获取My_Db_Table_Row_Person类的实例或Person的id。您可以将其视为一个新的抽象层,仅适用于您将业务逻辑(如发送电子邮件)放在其中的项目。作为旁注,Bill Karwin实际上致力于Zend_Db:)的开发。