我想从数据库中选择所有帖子及其附件。
这是具有伪数据的结构:
帖子表
id | post | userId |
---------|---------------|----------|
1 | "hello" | 1 |
2 | "world" | 1 |
3 | "ouch" | 2 |
4 | "test" | 1 |
附件表
id | postId | fileName | time |
---------|---------------|----------|----------|
1 | 1 |"hey.jpg" | 0 |
2 | 1 |"test.png"| 53252354 |
3 | 2 |"asd.png" | 0 |
4 | 4 |"asd2.png"| 0 |
到目前为止,我的代码看起来像这样,但是我并没有真正得到想要的。
$qry = $db->prepare('
SELECT p.id
, p.post
, p.userId
, att.fileName
, att.time
FROM posts p
LEFT
JOIN attachments att
ON att.postId = p.id
');
$qry->execute();
$postsArray = $qry->fetchAll(PDO::FETCH_ASSOC);
我想要这样的东西:
[{'id': 1,
'post': 'hello',
'userId': 1,
'attachments': [{'fileName': 'hey.jpg', 'time:' 0}, ... ]
}, ... ]
我该如何实现?
答案 0 :(得分:3)
您的查询将为您提供所需结果的正确数据,您可以在PHP中进行后处理以获得所需格式:
foreach ($postArray as $post) {
$fixed_part = array('id' => $post['id'], 'post' => $post['post'], 'userId' => $post['userId']);
$key = serialize($fixed_part);
if (!isset($out[$key])) $out[$key] = $fixed_part;
$out[$key]['attachments'][] = array('fileName' => $post['fileName'], 'time' => $post['time']);
}
$out = array_values($out);
echo json_encode($out, JSON_PRETTY_PRINT);
答案 1 :(得分:2)
通常我会做这样的事情:
$posts
请注意,$posts = array_values($posts);
数组是ID索引的。我会那样做。但是,如果您需要与问题完全相同的结果(零索引),则可以添加以下行:
select json_arrayagg(post_json) as json
from (
select json_object(
'id', p.id,
'post', p.post,
'userId', p.userId,
'attachments', json_arrayagg(
json_object('fileName', a.fileName, 'time', time)
)
) as post_json
from posts p
left join attachments a on a.postId = p.id
group by p.id
) x
在较新的MySQL版本中,您还可以通过单个SQL查询获取JSON结果:
[{"id": 1, "post": "hello", "userId": 1, "attachments": [{"time": 0, "fileName": "hey.jpg"}, {"time": 53252354, "fileName": "test.png"}]}, {"id": 2, "post": "world", "userId": 1, "attachments": [{"time": 0, "fileName": "asd.png"}]}, {"id": 3, "post": "ouch", "userId": 2, "attachments": [{"time": null, "fileName": null}]}, {"id": 4, "post": "test", "userId": 1, "attachments": [{"time": 0, "fileName": "asd2.png"}]}]
结果:
{{1}}