我想知道Doctrine 2和Propel 1.6的优点和缺点是什么。 例如,Doctrine 2实际上是用户友好的,但如果你想要超越顺从,就会限制你。 Doctrine 2文档缺乏更新......
如果可能的话,您可以分享您在Doctrine2表现良好或Propel完美的地方的经验。
提前致谢。
答案 0 :(得分:18)
<强> EDITED 强>
我只是joined the chat就此问题获得了一些见解。我们来一个简历:
<强>描述强>
Propel基于ActiveRecord模式和Doctrine,而是使用Data Mappers和Virtual Proxies。
当我第一次学习使用PHP的OOP时,ActiveRecord被广泛使用,大部分是由于Ruby On Rails的影响。然后开发人员开始意识到ActiveRecord是一个有限的概念,特别适用于大型应用程序。
为什么?
自己思考一下,域模型对象有责任知道如何自救吗?或者甚至将其数据转换为JSON格式?
答案是否定的,因为它违反了Single Responsibility Principle (SRP)和域cohesion。
Martin将责任定义为改变的理由,并得出结论 一个类或模块应该只有一个,而且只有一个可以改变。
假设您有一个Author
实体。你有什么理由改变它?
好吧,如果使用ActiveRecord实现,除了需要更改对象属性本身之外,如果实现特定于该对象的新类型持久性,则还需要更改它,就像我们在实现缓存策略时那样。
另外,假设Propel库改变了模型基类的方法(只是一个简单的例子)。现在您有理由更改应用程序中没有任何持久性的部分,因为您的实体与ORM基类紧密结合。换句话说,您的域模型对象不应该依赖于每个ORM框架的细节。您应该能够更改ORM,让您的域模型对象不受影响。
因此,活动记录要求您的域模型了解持久层的存在。 两个职责。
使用Active Record时最糟糕的事情就是你“搞砸”你的域模型继承层次结构。如果为了持久性目的而扩展基类的Human
实体,然后扩展Man
实体的Human
实体,如果由于某种原因,您有另一个Woman
实体扩展如果Human
实体无法持久化,那么您将打破基类建立的contract,该基类声明每个实体都需要知道如何保存自己。你将无法$woman->save()
。
严格地说,它也会导致违反Liskov Substitution Principle
最后,停止使用ActiveRecord 的最终原因。查看以下代码,您将能够看到ORM在事务期间将对象映射到存储的责任委托给域模型实体:
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你必须 每次保存或删除Book对象时都更新此新列; 这会使写查询慢一点,但读取查询的次数更多 快点。幸运的是,Propel模型对象支持前后挂钩 对于save()和delete()方法,所以这很容易 实施
因此,在单个模型实体中,您有: