gpt4 book ai didi

php - PHP ORM 如何将结果映射到对象(水化)

转载 作者:搜寻专家 更新时间:2023-10-31 20:47:59 25 4
gpt4 key购买 nike

如果我运行类似于以下的查询:

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 对象 User、Order 和 Payment 以及一个单一的数据库查询——它们是如何被水化的?我想查看伪代码、实际的 php 代码或我应该阅读的模式名称:)

最佳答案

因为没有答案,我将尝试描述我是如何解决这个问题的。这是一个玩具解决方案。

对数据库的查询是用一种我称之为 QQL 的小语言完成的,它的灵感来自于 Doctrine 2 DQL .

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

这会被解析并可以构建 SQL 语句。解析树还用于将结果集映射回对象图。

每个模型都描述了与其他模型的“关系”。所以User有一个一对多的Order,Order有一个一对多的Payment。描述在一个包含模型名称、主键和外键名称的数组中。

构建连接:

JOIN user order

检查用户模型,获取表名“users”,然后找到关系“order”,获取订单表名“orders”和连接键。使用它来构建:

JOIN orders o ON o.user_id=users.id

一旦查询运行并返回结果以构建对象图。我所做的是获取查询中使用的所有不同模型(在本例中为用户、订单和付款),然后为每一行 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
}
}

我的 hydrate 方法非常薄(快速),因为很多构建的对象都是重复的并被删除。从我的问题的结果集中,您可以看到 User('Jeff') 将被构建 5 次,其中 4 次是重复的,将被丢弃。

读取结果后,有 3 个对象列表。用户、订单和付款。这些与解析树一起传递给图形生成器。

Graph Builder 使用分析树来查看关系。从“根”模型(由“FROM 用户”确定)开始,检查已解析的 QQL 以找到请求的 JOIN(User->id TO 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 查询(3 毫秒)和释放 mysqli 结果(1 毫秒),包括模型类(0.7 毫秒)。写起来很有趣,只花了一天时间。

关于php - PHP ORM 如何将结果映射到对象(水化),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11192748/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com