php - Doctrine 2 和 Propel 1.6 的弱点和力量

标签 php doctrine-orm propel

<分区>

我想知道 Doctrine 2 和 Propel 1.6 的优势和弱点是什么。 例如,Doctrine 2 确实是用户友好的,但如果你想超越墨守成规,它就会限制你。 Doctrine 2 文档缺乏更新......

如果可能,您可以分享您的经验,了解 Doctrine2 的优势所在或 Propel 的优势所在。

提前致谢。

最佳答案

已编辑

我刚刚 joined the chat获得关于这个问题的一些见解。让我们制作一份简历:

Single Responsibility Principle

  • 只有 Doctrine 2.x 使用了 DataMapper 的一些想法
  • 开发人员仍然认为 ActiveRecord 是神赐的佳肴
  • 无法独立于数据库进行测试
  • 依赖注入(inject)的敌人

参见:https://softwareengineering.stackexchange.com/questions/119352/does-the-activerecord-pattern-follow-encourage-the-solid-design-principles

描述

Propel 基于 ActiveRecord Pattern 和 Doctrine,而是使用 Data MappersVirtual Proxies .

当我第一次了解 PHP 的 OOP 时,ActiveRecord 被广泛使用,主要是由于 Ruby On Rails 的影响。然后开发人员开始意识到 ActiveRecord 是一个有限的概念,特别适用于大型应用程序。

为什么?

自己想想,一个领域模型对象的职责是知道如何保存自己吗?或者甚至将其数据转换为 JSON 格式?

答案是否定的,因为它违反了Single Responsibility Principle (SRP)和域名 cohesion .

Martin defines a responsibility as a reason to change, and concludes that a class or module should have one, and only one, reason to change.

假设您有一个 Author 实体。你会因为什么原因改变它? 好吧,如果使用 ActiveRecord 实现,除了需要更改对象属性本身之外,如果您实现特定于该对象的新型持久性,您还需要更改它,就像我们在实现缓存策略时所做的那样。

此外,假设 Propel 库更改了模型基类的方法(只是一个简单的示例)。现在您有理由更改应用程序的其他部分,这些部分与持久性无关,因为您的实体与 ORM 基类紧密耦合。换句话说,您的域模型对象不应依赖于每个 ORM 框架的细节。您应该能够更改 ORM,让您的域模型对象保持不变。

因此,事件记录需要您的域模型了解持久层的存在。有两个职责

使用 Active Record 时最糟糕的事情是你“搞砸了”你的领域模型继承层次结构。如果您有一个 Human 实体扩展基类用于持久性目的,然后有一个 Man 实体扩展 Human 实体,如果出于某种原因您如果有另一个 Woman 实体扩展了 Human 实体而没有持久化的能力,那么您将破坏 contract由基类建立,声明每个实体都需要知道如何保存自己。你将无法执行 $woman->save()

严格来说,也导致违反了Liskov Substitution Principle

最后,停止使用 ActiveRecord 的最终原因。查看以下代码,您将能够看到 ORM 在事务期间将对象映射到存储的责任委托(delegate)给了域模型实体:

class Book extends BaseBook
{
  public function postSave(PropelPDO $con)
  {
    $this->updateNbBooks($con);
  }

  public function postDelete(PropelPDO $con)
  {
    $this->updateNbBooks($con);
  }

  public function updateNbBooks(PropelPDO $con)
  {
    $author = $this->getAuthor();
    $nbBooks = $author->countBooks($con);
    $author->setNbBooks($nbBooks);
    $author->save($con);
  }
}

http://www.propelorm.org/documentation/06-transactions.html You must update this new column every time you save or delete a Book object; this will make write queries a little slower, but read queries much faster. Fortunately, Propel model objects support pre- and post- hooks for the save() and delete() methods, so this is quite easy to implement

因此,在单个模型实体中,您有:

  1. 坚持不懈
  2. 拦截过滤器模式以进行前后保存/删除
  3. 验证(http://www.propelorm.org/documentation/05-validators.html)
  4. 缓存
  5. 然后你去...

关于php - Doctrine 2 和 Propel 1.6 的弱点和力量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12026020/

相关文章:

javascript - 通过 AJAX 发送数据并获取 JSON 响应

php - 迭代大量记录以在 Doctrine 中生成报告

php - Doctrine 2 连接表错误?

mysql - 强制 Doctrine 将类型 ="guid"创建为 VARCHAR(255) 而不是 CHAR(36)

php - 使用 Composer 安装 Propel 行为

php - 在构造函数中注入(inject)所有变量或使用 setter 并在未设置时抛出异常是更好的做法吗?

javascript - 使用 PHP 和 JS 将 div = contenteditable 保存到 MySQL

php - 使用 PHP 删除 Amazon S3 中的文件夹

php - 是否可以使用 Propel2 进行全文(匹配)查询?

php - 如何在 propel 中从多对多关系中检索行?