gpt4 book ai didi

php - 从 MySQL 结果和 PHP 为 D3.js 树创建分层 JSON?

转载 作者:行者123 更新时间:2023-11-29 05:02:14 27 4
gpt4 key购买 nike

我正在尝试使用 PHP 从数据库结果创建以下 JSON(大大简化...):

{
"name": "Bob",
"children": [{
"name": "Ted",
"children": [{
"name": "Fred"
}]
},
{
"name": "Carol",
"children": [{
"name": "Harry"
}]
},
{
"name": "Alice",
"children": [{
"name": "Mary"
}]
}
]
}

数据库表:

Table 'level_1':

level_1_pk| level_1_name
-------------------------
1 | Bob


Table 'level_2':

level_2_pk| level_2_name | level_1_fk
-------------------------
1 | Ted | 1
2 | Carol | 1
3 | Alice | 1


Table 'level_3':

level_3_pk| level_3_name | level_2_fk
-------------------------
1 | Fred | 1
2 | Harry | 2
3 | Mary | 3

代码:

$query = "SELECT * 
FROM level_1
LEFT JOIN level_2
ON level_1.level_1_pk = level_2.level_1_fk";
$result = $connection->query($query);
while ($row = mysqli_fetch_assoc($result)){
$data[$row['level_1_name']] [] = array(
"name" => $row['level_2_name']
);
}

echo json_encode($data);

产生:

{"Bob":[{"name":"Ted"},{"name":"Carol"},{"name":"Alice"}]}

问题:

如何获取下一级 level_3,并按照上面定义的 JSON 的要求在 JSON 中包含文本“children”和 level_3 children?

我想如果 JSON 中有更多子项,我将需要 PHP 递归。

SQL

最佳答案

这看起来不像是分层数据的体面设计。考虑另一种方法,例如邻接列表

解决方案 #1 - MySQL 8 JSON 支持:

对于 MySQL 8,您可以使用 JSON_ARRAYAGG()JSON_OBJECT()仅使用 SQL 获取 JSON 结果:

select json_object(
'name', l1.level_1_name,
'children', json_arrayagg(json_object('name', l2.level_2_name, 'children', l2.children))
) as json
from level_1 l1
left join (
select l2.level_2_name
, l2.level_1_fk
, json_arrayagg(json_object('name', l3.level_3_name)) as children
from level_2 l2
left join level_3 l3 on l3.level_2_fk = l2.level_2_pk
group by l2.level_2_pk
) l2 on l2.level_1_fk = l1.level_1_pk
group by level_1_pk

结果是:

{"name": "Bob", "children": [{"name": "Ted", "children": [{"name": "Fred"}]}, {"name": "Carol", "children": [{"name": "Harry"}]}, {"name": "Alice", "children": [{"name": "Mary"}]}]}

db-fiddle demo

格式化:

{
"name": "Bob",
"children": [
{
"name": "Ted",
"children": [
{
"name": "Fred"
}
]
},
{
"name": "Carol",
"children": [
{
"name": "Harry"
}
]
},
{
"name": "Alice",
"children": [
{
"name": "Mary"
}
]
}
]
}

解决方案 #2 - 使用 GROUP_CONCAT() 构造 JSON:

如果名称不包含任何引号字符,您可以使用 GROUP_CONCAT() 在旧版本中手动构建 JSON 字符串:

$query = <<<MySQL
select concat('{',
'"name": ', '"', l1.level_1_name, '", ',
'"children": ', '[', group_concat(
'{',
'"name": ', '"', l2.level_2_name, '", ',
'"children": ', '[', l2.children, ']',
'}'
separator ', '), ']'
'}') as json
from level_1 l1
left join (
select l2.level_2_name
, l2.level_1_fk
, group_concat('{', '"name": ', '"', l3.level_3_name, '"', '}') as children
from level_2 l2
left join level_3 l3 on l3.level_2_fk = l2.level_2_pk
group by l2.level_2_pk
) l2 on l2.level_1_fk = l1.level_1_pk
group by level_1_pk
MySQL;

结果是一样的(参见 demo )

解决方案 #3 - 使用 PHP 对象构造 nestet 结构:

您还可以编写更简单的 SQL 查询并在 PHP 中构建嵌套结构:

$result = $connection->query("
select level_1_name as name, null as parent
from level_1
union all
select l2.level_2_name as name, l1.level_1_name as parent
from level_2 l2
join level_1 l1 on l1.level_1_pk = l2.level_1_fk
union all
select l3.level_3_name as name, l2.level_2_name as parent
from level_3 l3
join level_2 l2 on l2.level_2_pk = l3.level_2_fk
");

结果是

name    | parent
----------------
Bob | null
Ted | Bob
Carol | Bob
Alice | Bob
Fred | Ted
Harry | Carol
Mary | Alice

demo

注意:名称在所有表中应该是唯一的。但我不知道如果可能出现重复,您会期望得到什么结果。

现在将行作为对象保存在由名称索引的数组中:

$data = []
while ($row = $result->fetch_object()) {
$data[$row->name] = $row;
}

$data 现在将包含

[
'Bob' => (object)['name' => 'Bob', 'parent' => NULL],
'Ted' => (object)['name' => 'Ted', 'parent' => 'Bob'],
'Carol' => (object)['name' => 'Carol', 'parent' => 'Bob'],
'Alice' => (object)['name' => 'Alice', 'parent' => 'Bob'],
'Fred' => (object)['name' => 'Fred', 'parent' => 'Ted'],
'Harry' => (object)['name' => 'Harry', 'parent' => 'Carol'],
'Mary' => (object)['name' => 'Mary', 'parent' => 'Alice'],
]

我们现在可以在一个循环中链接节点:

$roots = [];
foreach ($data as $row) {
if ($row->parent === null) {
$roots[] = $row;
} else {
$data[$row->parent]->children[] = $row;
}
unset($row->parent);
}

echo json_encode($roots[0], JSON_PRETTY_PRINT);

结果:

{
"name": "Bob",
"children": [
{
"name": "Ted",
"children": [
{
"name": "Fred"
}
]
},
{
"name": "Carol",
"children": [
{
"name": "Harry"
}
]
},
{
"name": "Alice",
"children": [
{
"name": "Mary"
}
]
}
]
}

demo

如果可能有多个根节点(level_1_name中的多行),则使用

json_encode($roots);

关于php - 从 MySQL 结果和 PHP 为 D3.js 树创建分层 JSON?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56073857/

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