微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

PHP ORM如何将结果映射到对象(水合)

如果我运行查询类似语句以:

SELECT * FROM user u
LEFT JOIN orders o ON o.user_id=u.id
LEFT JOIN payments p ON p.order_id=o.id

结果数据如下:

u.id, u.name, o.id, o.item, o.date_time, p.id, p.amount, p.date_time
  99    jeff    17  spring   12-12-2012    12     10.99   13-12-2012
  99    jeff    18     jam   12-12-2012    13       .99   16-12-2012
  99    jeff    19     car   22-12-2012    14      1000   17-12-2012
  99    jeff    19     car   22-12-2012    15      1000   18-12-2012
  99    jeff    19     car   22-12-2012    16      1000   19-12-2012

因此,用户Jeff有3个订单,他已经向自己的汽车支付了3笔款项.

PHP对象用户,订单和付款以及一个数据库查询-它们如何水合?我想查看伪代码,实际的PHP代码或应该在其上阅读的模式名称:)

解决方法:

因为没有答案,所以我将尝试描述如何解决此问题.这是一种玩具解决方案.

数据库查询是用一种叫做QQL的小语言完成的,这是受《 Doctrine 2 DQL》启发的.

SELECT *
FROM user
JOIN user order
JOIN order payment
WHERE user.name=?

将对此进行解析,并可以构建sql语句.解析树还用于将结果集映射回对象图.

每个模型都有与其他模型的“关系”描述.因此,用户具有一对多订购,订单具有一对多付款.描述位于一个数组中,该数组包含模型名称,主键和原键名.

要建立JOIN:

JOIN user order

检查User模型,获取名称“ users”,然后找到关系“ order”,获取Order表名称“ orders”和联接键.使用它来构建:

JOIN orders o ON o.user_id=users.id

一旦查询运行并返回结果以构建对象图.我要做的是获取查询中使用的所有不同模型(在本例中为User,Order和Payment),然后为每一行Hydrate每行:

// query DB and get results into an array called $rows
foreach ($rows as $row) {
    foreach (array('User', 'Order', 'Payment') as $model) {
        $o = new $model;
        $o->hydrate($row);
        // inspect primary key - have we got this object already? store or throw away
    }
 }

我的水合方法非常薄(快速),因为构建的许多对象将重复出现并被删除.从我的问题的结果集中,您可以看到User(‘Jeff’)将被构建5次,其中4次重复并且将被丢弃.

读取结果后,将有3个对象列表.用户,订单和付款.它们与解析树一起传递到Graph Builder.

Graph Builder使用解析树查看关系.从“ root”模型(由“ FROM用户”确定)开始,检查已解析的QQL以查找请求的JOIN(用户-> id至Order-> user_id),将订单添加到User-> orders数组.然后,它对(Order-> id TO Payment-> order_id)执行相同的操作.

结果是:

$user->name == 'jeff'
$user->orders[0]->item == 'spring'
$user->orders[1]->item == 'jam'
$user->orders[2]->item == 'car'
$user->orders[2]->payments[2]->date_time == '19-12-2012'

我最后得到了四个主要类,即ORM,所有模型都扩展的Model_Base(确保每个模型都有一个“表名”,“列”和“关系”),一个QQLParser和一个Graph Builder.迄今为止,ORM类最大,有近200条线.

结论.有用.感觉类似于Doctrine 2,因此我最终过渡到使用Doctrine 2的痛苦会减少.可能会更有效率.对测试页面进行概要分析的结果是读取数千个对象,到目前为止,最慢的部分是SQL查询(3ms)和释放MysqLi结果(1ms),包括模型类(0.7ms).写作很有趣,只花了一天的时间.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐