我有一个简单的数据库表,它通过父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中,出于性能原因,当执行查询时,迭代器会将数据库游标包装到结果上。

$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上索引结果,为每个父id提供子id,并使用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)

然后结果集将按父id排序,因此$iterator->get($parent_id)将返回一个子实体数组(或空),但这看起来更像是一个黑客而不是一个真正的特性。
另一方面,考虑到这个问题,似乎可以在内部创建专门的灵活实体来实现对儿童的智能化。

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

10-16 01:51