我对Rails ActiveRecord,Doctrine for PHP(以及类似的ORM)背后的一些设计感兴趣。
显然这是一个学术问题,但欢迎各种答案!
(我选择的语言是OO PHP5.3!)
答案 0 :(得分:3)
链式方法调用与ORM问题正交,它们在OOP中被遍地使用。可链式方法只返回对当前对象的引用,允许调用返回值。在PHP中
class A {
public function b() {
...
return $this;
}
public function c($param) {
...
return $this;
}
}
$foo = new A();
$foo->b()->c('one');
// chaining is equivilant to
// $foo = $foo->b();
// $foo = $foo->c();
至于如何构造查询,有两种方法。在像ORM这样的ActiveRecord中,有代码可以检查数据库的元数据。大多数数据库都有某种类似SQL或SQL的命令来查看这个元数据。 (MySQL的DESCRIBE TABLE
,Oracle的USER_TAB_COLUMNS
表等)
有些ORM用中性语言(如YAML)描述数据库表。其他人可能会从您创建对象模型的方式推断数据库结构(我想说Django会这样做,但是我看了它已经有一段时间了)。最后,有一种混合方法,其中使用了前两种技术中的任何一种,但提供了一个单独的工具来自动生成YAML /等。或类文件。
一个表的名称和数据类型是已知的,很容易实际编写返回所有行的SQL查询,或者符合特定条件的特定行集。
关于你的上一个问题,
ORM如何管理查询 维持所有人的任意性质 这是预期的吗?
我认为答案是“不太好”。一旦你超越了单表,单对象的比喻,每个ORM都有一个不同的方法,一个关于如何使用SQL查询来建模对象的哲学。在摘要中,它就像添加基于ORM假设构建查询的新方法一样简单(即Zend_Db_Table的“findManyToManyRowset”方法)
答案 1 :(得分:2)
ORM如何设法完成链接访问器等功能以及它们通常需要的工作深度?
似乎没人回答这个问题。我可以快速描述Doctrine如何在PHP中实现这一点。
在Doctrine中,您在对象模型上看到的所有字段都不是为该类实际定义的。因此,在您的示例中,$ car->所有者,$ car类中没有定义称为“所有者”的实际字段。
相反,ORM使用像__get and __set这样的魔术方法。所以当你使用像$ car-> color这样的表达式时,内部PHP会调用Doctrine_Record #__ get('color')。
此时,ORM可以自由地满足此要求。这里有很多可能的设计。例如,它可以将这些值存储在名为$ _values的数组中,然后返回$ this-> _values ['color']。特别是,Doctrine不仅跟踪每条记录的值,还跟踪它相对于数据库中持久性的状态。
不直观的一个例子是与Doctrine的关系。当您获得对$ car的引用时,它与People表的关系称为“所有者”。因此,$ car->所有者的数据实际上存储在与$ car本身的数据不同的表中。所以ORM有两个选择:
当然,Doctrine使用#2,因为#1对任何具有中等复杂性的真实生产站点都变得笨重。但它也有副作用。如果你在$ car上使用了几个关系,那么当你访问它时,Doctrine会分别加载每个关系。所以当你可能只需要1个查询时,你最终会运行5-6个查询。
Doctrine允许您使用Doctrine查询语言优化这种情况。您告诉DQL您要加载汽车对象,还要将其加入其所有者,制造商,标题,留置权等,并将所有数据加载到对象中。
呼!反应很快。但基本上,你已经明白了“ORM的目的是什么?”的核心。和“我们为什么要用一个?” ORM允许我们在大多数时间继续思考对象模式,但抽象并不完美,抽象中的泄漏往往会出现性能损失。
答案 2 :(得分:1)
我创建了一个关于构建可能对您感兴趣的PHP DataMapper主题的演示文稿。它是在Oklahoma City Coworking Collaborative的视频中录制的,当时我在那里为PHP用户组提出了这个视频:
视频: http://blip.tv/file/2249586/
演示幻灯片: http://www.slideshare.net/vlucas/building-data-mapper-php5-presentation
该演示文稿基本上是phpDataMapper的早期概念,尽管此后发生了很多变化。
希望它们能帮助您更好地理解ORM的内部工作原理。
答案 3 :(得分:0)
链式访问器并不是什么大问题:来自setter方法的return $this
。繁荣,完成,可以在任意级别上工作。