gpt4 book ai didi

php - Pomm 项目中具有水化模型的树结构

转载 作者:行者123 更新时间:2023-11-29 13:27:15 24 4
gpt4 key购买 nike

我有一个简单的数据库表,它通过 parent_id 属性实现树结构。像这样:

+----+------+-----------+
| id | name | parent_id |
+----+------+-----------+
| 1 | test | null |
+----+------+-----------+
| 2 | tes2 | 1 |
+----+------+-----------+
| 3 | tes3 | 2 |
+----+------+-----------+
| 4 | tst | 2 |
+----+------+-----------+

我想获取具有树结构的 PHP 对象。所以对象类别将具有属性子类别,这将是类别对象列表等。我想通过使用 Pomm 的递归 SQL 查询直接从 PostgreSQL 数据库获取此对象.目标不是遍历获取的数据并在 PHP 中构建此类对象。我想要直接处理 PostreSQL -> Pomm -> 对象。

至于现在,我只在第一级就得到了我想要的。所以第一级类别有子类别,这是类别实体的列表。然而,下一层(深度 2)没有子类别。

到目前为止,我有这个:

$sql = <<<SQL
with recursive
cat as (select c.* FROM :category c where parent_id is null),
subcat as (
select c.* from :category c join cat on c.parent_id=cat.id
union all
select c.* from :category c join subcat on c.parent_id=subcat.id
)
select :projection from cat cc, subcat
where cc.id=subcat.parent_id
group by :group_fields
SQL;

$projection = $this->createProjection()
->setField('subcategories', 'array_agg(subcat)', 'public.category[]');
$sql = strtr($sql, [
':category' => $this->structure->getRelation(),
':projection' => $projection->formatFieldsWithFieldAlias('cc'),
':group_fields' => $this->createProjection()->formatFields('cc'),
]);

我的问题是 Pomm 是否可行,如果可行,如何实现?

最佳答案

您想要实现的目标实际上并不能直接实现,因为在 Pomm 中,出于性能原因,当执行查询时,迭代器会将数据库游标包装在结果上。

$iterator = $this->query($sql, $array_of_parameters);

foreach ($iterator as $entity) {
$entity->getParentId();
}

每次从迭代器中获取数据时,转换器系统都会将其转换为实体。但是实体不知道数据库,因此它们无法使用访问器获取更多数据。

一个简单的想法是获取包含所有结果作为嵌套实体的单个结果:

with recursive
cat as (
select * from test_tree tt where not exists (select parent_id from test_tree tt2 where tt2.parent_id = tt.id)
union all
select tt.*, array_agg(child) from test_tree tt join cat child on tt.id = child.parent_id group by tt.id
)
select * from cat

但不幸的是,不可能在 CTE 的递归项中使用聚合函数。

另一个想法是在 id 上索引结果,为每个 parent_id 提供 child ,并使用可滚动的 Pomm 迭代器来获取它们:

with
tree as (
select
tt.id,
array_agg(child) as children
from
test_tree tt
join lateral (select * from test_tree tt2 where tt2.parent_id = tt.id) child on (true) group by tt.id
)
select
idx as id,
tree.children
from
generate_series(1, (select max(id) from test_tree)) idx
left join tree on tree.id = idx

哪些输出:

┌────┬─────────────────────────────────────────┐
│ id │ children │
├────┼─────────────────────────────────────────┤
│ 1 │ {"(2,\"test 2\",1)","(3,\"test 3\",1)"} │
│ 2 │ {"(4,\"test 4\",2)","(5,\"test 5\",2)"} │
│ 3 │ {"(6,\"test 6\",3)"} │
│ 4 │ ¤ │
│ 5 │ ¤ │
│ 6 │ {"(7,\"test 7\",6)"} │
│ 7 │ ¤ │
└────┴─────────────────────────────────────────┘
(7 rows)

然后结果集将按 parent_id 排序,因此 $iterator->get($parent_id) 将返回子实体数组(或 null),但这看起来更像是 hack 而不是真实的功能。

从另一端看问题,似乎可以创建专用的灵活实体 embed a nested set design pattern在内部对 child 进行递归。

关于php - Pomm 项目中具有水化模型的树结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31540514/

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