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

发布于 2024-10-15 00:09:06 字数 918 浏览 1 评论 0原文

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

我目前正在学习 ZF 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 protected]";
$user->save();

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

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

为每个实体拥有一个 Row 类有什么好处?谁能向我指出这方面的最佳实践。

Extended Question: Why should I use data mapper / Db_Table_Row, where as DbTable is capable of handling most of the basic tasks for data manipulation.

I am currently learning ZF v1.11

For Database manipulation, I created DbTable for each tables. For example, "users" table is represented by Application_Model_DbTable_Users with no additional codes in there.

When manipulating data, I can use:

<?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 protected]";
$user->save();

My Question is, when would I need to define a row class (assuming Table_Row is referred as DataMapper in ZF-Tutorials)

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

What are the benefits of having a Row class for each entity? Can anyone point me to best practices for this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

风追烟花雨 2024-10-22 00:09:06

您不需要定义自己的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();

另一个示例,当您想要创建自定义删除或插入方法。假设您想确保不想使用 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

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

You do not need to define your own Table_Row. However, it maybe useful in many cases, particularly if you want to define some specific methods or properties for a given user row. They can also improve readability of your code.

For example in your Users table case, you could define a method called getFullName() in a custom user row as:

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

Then when you obtain user row object, to get the full name of the user, you just do:

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

Second example is when you have some parent table to the Users table, such as Addresses. In this case you could define a method called getAddress in a user row:

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

In this scenario, you would get an Address row object for a current user as follows:

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

Another example, would be when you want to create custom delete or instert methods. Lets assume that you want to make sure you do not want to delete an admin user using delete() method. Then you could overload delete method from Zend_Db_Table_Row as follows:

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

This way, you would not be able to delete an admin user just by calling delete() on a user row object:

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

These are just three basic examples showing usefulness of defining your own row classes. But of course they are not necessary. However, from my own experience they are quite handy.

各空 2024-10-22 00:09:06

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

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

Zend_Db_Table_Row行数据网关模式的实现。在这里,返回的对象看起来与数据库记录一模一样,它们包含处理该数据的业务逻辑,但它们不包含对它们所在的表(即 ActiveRecord)进行 CRUD 的逻辑,而是聚合它们。

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

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

In a nutshell: it's about isolation.

Zend_Db_Table is an implementation of the Table Data Gateway. It channels CRUD access to a specific table view through one class. It is usually used with a Table Module, e.g. a class that contains the business logic for the records handled by a gateway.

Zend_Db_Table_Row is an implementation of the Row Data Gateway Pattern. Here, the returned objects look exactly like a database record and they contain the business logic to work with that data, but they don't contain the logic to CRUD with the table they are from (that would be an ActiveRecord) but aggregate them.

Row Data Gateways are fine as long as you don't have too much object relational impedance mismatch. How an object is persisted in a relational database and how it should look like in an object world are often quite different things. When using a Domain Model, your business objects are usually structured in a different way than they are stored in the database. Thus, you cannot easily CRUD them from the database. This is where DataMapper comes into play.

A DataMapper takes the responsibility of mapping Domain objects onto Recordsets and vice versa. This makes your application more maintainable because it decouples your Domain objects from the Database structure. It keeps them separated and gives you more flexibility in how to model both layers (persistence and domain).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文