PHP / MySQL OOP:从SQL加载复杂对象

时间:2009-08-28 20:24:08

标签: php mysql oop

所以我正在为房地产经纪人做一个项目。我的设计中有以下对象/ MySQL表:

Complexes
Units
Amenities
Pictures
Links
Documents
Events
Agents

这些是上述对象之间的关系。

Complexes have a single Agent.
Complexes have multiple Units, Amenities, Pictures, Links, Documents, and Events.
Units have multiple Pictures, Links, and Documents.

设施,图片,链接,文档和事件都在数据库中具有必要的外键,以指定它们属于哪个单元/复合体。

我需要将数据库中的必要对象加载到PHP中,以便在项目中使用它们。

如果我尝试在1个查询中从表中选择所有数据,使用LEFT JOINS,我将得到每个唯一的至少(链接数)*(图片数)*(文档数)行单元。添加设施和活动,我会得到所有*设施*每个复杂的事件#...不确定我想尝试将其加载到PHP中的对象。

另一种可能性是每个复杂/单元,为链接,图片,文档,事件和便利设施执行1个单独的SQL语句

我的问题如下:

如果我正确索引我的所有表格,对每个复杂/单位执行3-5次额外查询真是个坏主意吗?

如果没有,我怎样才能获得加载到PHP对象中所需的数据。理想情况下,我会为单位设置如下对象:

Unit Object
(
    [id]
    [mls_number]
    [type]
    [retail_price]
    [investor_price]
    [quantity]
    [beds]
    [baths]
    [square_feet]
    [description]
    [featured]
    [year_built]
    [has_garage]
    [stories]
    [other_features]
    [investor_notes]
    [tour_link]
    [complex] => Complex Object
        (
            [id]
            [name]
            [description]
            etc.
        )
    [agent] => Agent Object
        (
            [id]
            [first_name]
            [last_name]
            [email]
            [phone]
            [phone2] 
            etc.

        )
    [pictures] => Array
        (
            [1] => Picture Object
                (
                )
        )
    [links] => Array
        (
            [1] => Link Object
                (
                )
        )
    [documents] => Array
        (
            [1] => Document Object
                (
                )
        )    
)

我不总是需要所有这些信息,有时我只需要复杂的主键,有时我只需要代理的主键等。但我认为正确的方法是这样做每次实例化时都加载整个对象。

我一直在对OO PHP进行大量研究,但大多数(阅读全部)在线示例仅使用1个表。这显然无济于事,因为我正在研究的项目有很多复杂的关系。有任何想法吗?我完全不在这里吗?

由于

[UPDATE]

另一方面,通常在每个人都会看到的前端,我将需要所有信息。例如,当有人想要关于特定复合体的信息时,我需要显示属于该复合体的所有单元,所有图片,文档,链接,复合体的事件以及该单元的所有图片,文档和链接。

我希望避免的是,在一个页面加载期间,执行一个查询以获得我需要的复杂。然后另一个查询来获得与该复合体相关的20个单元。然后对于20个单元中的每个单元,执行图片查询,另一个查询文档,另一个查找链接等。我想一次性完成所有这些操作,一次通过数据库。

[编辑2] 另请注意,从数据库中选择图片,文档,链接,事件和代理的查询非常简单。只是基本SELECT [列列表] FROM [table] WHERE [primary_key] = [value]偶尔INNER JOIN。我不做任何复杂的计算或子查询,只是基本的东西。

[BENCHMARK] 所以在阅读了我的问题的所有答案之后,我决定对我决定做的事情进行基准测试。我所做的是加载我需要的所有单位。然后,因为我需要显示图片,文档,等等,我当时加载它们。我创建了30,000个测试单元,每个单元有100张图片,100个文档和100个链接。然后我加载了一定数量的单位(我从1000开始,然后是100,然后是更真实的10),循环浏览它们,然后加载与单元相关的所有图片,文档和链接。有1000个单位,大约需要30秒。有100个单位,花了大约3秒钟。有10个单位,花了大约0.5秒。结果存在很多差异。有时,有10个单位,需要0.12秒。然后需要.8。然后也许.5。然后.78。真的到处都是。然而,它似乎平均约半秒钟。但实际上,我可能一次只需要6个单元,而且它们每个可能只有10个图片,5个链接和5个与之相关的文档......所以我认为“在需要时抓取数据”的方法是在这种情况下最好的选择。如果你需要一次性获取所有这些数据,那么有必要提出一个SQL语句来加载你需要的所有数据,这样你只需要循环数据一次(6700个单位一次需要217秒)而全部30,000个PHP使内存不足)。

5 个答案:

答案 0 :(得分:4)

  

如果我正确索引我的所有表格,对每个复杂/单位执行3-5次额外查询真是个坏主意吗?

简而言之,没有。对于每个相关表,您应该运行单独的查询。这就是大多数ORM(对象关系映射/建模)系统所能做到的。

如果性能真的是一个问题(根据你所说的,它不会),那么你可以考虑使用APC,memcache或Xcache等缓存结果。

答案 1 :(得分:0)

ORM的意思是不是每次都加载整个对象。关键是要让您的应用轻松透明地访问对象。

如上所述,如果需要单位对象,则加载单位对象,只加载单位对象。如果需要代理对象,则在需要时加载,而不是在加载单元对象时加载。

答案 2 :(得分:0)

也许你应该考虑打破这个。

启动对象时,只获取该对象运行所需的详细信息。如果您需要更多细节,那就去拿吧。你以这种方式分配你的负载和处理:对象只获得它需要运行的负载和处理,当需要更多时,它就得到它。

因此,在您的示例中 - 首先创建复合体。当您需要访问某个单元,然后在需要该代理时创建该单元,然后获取该代理等。

$complexDetails = array('id' => $id, etc);
$complexUnits = array();
.........
$complexUnits[] = new unit();
.........
$complexDetails['agent'] = new Agent();

答案 3 :(得分:0)

当我将自己的MVC框架编造为实验时,我不得不解决这个问题。为了限制从DB加载的数据层,我将一个整数传递给构造函数。每个构造函数在将它传递给它实例化的对象的构造函数之前会递减此整数。当它达到0时,将不再实例化子对象。这意味着,基本上,传递的int是加载的层数。

因此,如果我只想要单位对象的属性,我会这样做:

$myUnit = new Unit($unitId,1);

答案 4 :(得分:0)

如果你想“存储”对象,意味着缓存它们,只需将它们加载到PHP数组中并序列化即可。然后,您可以将其存储回数据库,memcache或其他任何位置。附加标签可以让你检索它,并包含一个时间戳,以便你知道它的年龄(即需要刷新)。

如果数据没有变化,或者不经常更改,那么每次都没有理由运行多个复杂查询。简单的,比如获得一个主要的,你也可以直接点击数据库。