如何通过PHP+PDO+MySQL生成多层嵌套JSON输出
嘿,我懂你现在的处境——已经搞定了PDO的基础连接和表操作,结果卡在了生成想要的多层嵌套JSON这一步,对吧?别慌,我给你拿一个常见的「文章-评论」嵌套场景举例,一步步教你怎么实现,你可以根据自己的表结构直接套用。
第一步:先明确你的目标嵌套结构
假设你想要的JSON是这样的(每篇文章下包含它的所有评论):
[ { "post_id": 1, "title": "我的第一篇文章", "content": "这是文章内容", "created_at": "2024-05-20 10:00:00", "comments": [ { "comment_id": 1, "author": "张三", "text": "写得真好!", "created_at": "2024-05-20 10:30:00" } ] } ]
第二步:用PDO构建嵌套数组
这里有两种常用的实现方式,你可以根据数据量和需求选择:
方式一:先查顶层数据,再循环查子数据(适合小数据量)
这种方式逻辑简单,容易理解,适合数据量不大的场景:
// 1. 基础PDO连接(你已经会,这里再贴一遍确保完整) $dsn = 'mysql:host=localhost;dbname=你的数据库名;charset=utf8mb4'; $username = '你的用户名'; $password = '你的密码'; try { $pdo = new PDO($dsn, $username, $password); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch(PDOException $e) { die("数据库连接失败: " . $e->getMessage()); } // 2. 查询所有文章 $postsStmt = $pdo->prepare("SELECT post_id, title, content, created_at FROM posts"); $postsStmt->execute(); $posts = $postsStmt->fetchAll(PDO::FETCH_ASSOC); // 3. 遍历每篇文章,查询对应的评论并嵌套进去 foreach ($posts as &$post) { $commentsStmt = $pdo->prepare("SELECT comment_id, author, text, created_at FROM comments WHERE post_id = ?"); $commentsStmt->execute([$post['post_id']]); // 把评论数组赋值给当前文章的comments字段 $post['comments'] = $commentsStmt->fetchAll(PDO::FETCH_ASSOC); } unset($post); // 解除引用,避免后续操作污染数组 // 4. 转换为JSON并输出 header('Content-Type: application/json'); // 一定要设置正确的响应头 echo json_encode($posts, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
方式二:一次关联查询,再重组数组(适合大数据量)
如果你的数据量比较大,多次查询数据库会影响性能,这时候可以用LEFT JOIN一次性取出所有数据,再在PHP里重组嵌套结构:
// 1. 同样先做PDO连接(省略,和上面一样) // 2. 一次查询文章和对应的评论 $stmt = $pdo->prepare(" SELECT p.post_id, p.title, p.content, p.created_at AS post_created, c.comment_id, c.author, c.text, c.created_at AS comment_created FROM posts p LEFT JOIN comments c ON p.post_id = c.post_id "); $stmt->execute(); $allData = $stmt->fetchAll(PDO::FETCH_ASSOC); // 3. 重组数据为嵌套结构 $posts = []; foreach ($allData as $row) { $postId = $row['post_id']; // 如果当前文章还没加入数组,先添加文章的基础信息 if (!isset($posts[$postId])) { $posts[$postId] = [ 'post_id' => $row['post_id'], 'title' => $row['title'], 'content' => $row['content'], 'created_at' => $row['post_created'], 'comments' => [] ]; } // 如果这条数据有评论(LEFT JOIN可能返回null),就添加到评论数组 if ($row['comment_id'] !== null) { $posts[$postId]['comments'][] = [ 'comment_id' => $row['comment_id'], 'author' => $row['author'], 'text' => $row['text'], 'created_at' => $row['comment_created'] ]; } } // 把关联数组转成索引数组(可选,看你的需求) $posts = array_values($posts); // 4. 输出JSON header('Content-Type: application/json'); echo json_encode($posts, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
关键注意点
- 用
PDO::FETCH_ASSOC获取关联数组,这样键名和数据库字段对应,方便构建结构; json_encode的两个参数很重要:JSON_PRETTY_PRINT让JSON格式更易读,JSON_UNESCAPED_UNICODE避免中文被转义;- 输出前一定要设置
Content-Type: application/json,这样客户端(比如前端)才能正确识别这是JSON数据; - 如果你的嵌套层级更多(比如「分类-文章-评论」),只需要在现有逻辑上再加一层循环或数据重组即可。
内容的提问来源于stack exchange,提问作者ekspresyon
相关产品推荐
相关产品推荐

