首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP + MySQL 實現論壇階層式回覆與分頁顯示:遞迴函數、樹狀結構渲染完整範例

     編輯:PHP 相關知識

資料表設計:鄰接清單模型

CREATE TABLE bbsrow (
    bbsrow_id       INT(6) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    bbsrow_auth     VARCHAR(20) NOT NULL,
    bbsrow_parentid INT(6) DEFAULT NULL,      -- 父文章 ID,NULL 為主題文
    bbsrow_title    VARCHAR(200) NOT NULL,
    bbsrow_returncount INT(3) DEFAULT NULL,   -- 回覆數統計
    bbsrow_content  TEXT,                     -- 文章內容
    bbsrow_posttime DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

核心邏輯:遞迴顯示子回覆

function showChildren($parent_id, $depth = 0) {
    global $conn;
    $sql = "SELECT * FROM bbsrow WHERE bbsrow_parentid = " . intval($parent_id) . " ORDER BY bbsrow_posttime";
    $result = mysql_query($sql, $conn);
    
    if (mysql_num_rows($result) == 0) return;
    
    echo "
    "; while ($row = mysql_fetch_assoc($result)) { echo "
  • "; // 縮排視覺化 echo str_repeat("  ", $depth); echo "{$row['bbsrow_title']} by {$row['bbsrow_auth']} "; echo "({$row['bbsrow_posttime']})
    "; echo nl2br(htmlspecialchars($row['bbsrow_content'])); // 遞迴顯示子回覆 if ($row['bbsrow_returncount'] > 0) { showChildren($row['bbsrow_id'], $depth + 1); } echo "
  • "; } echo "
"; }

主程式流程

<?php
$conn = mysql_connect("localhost", "user", "pass") or die("連線失敗");
mysql_select_db("forum", $conn) or die("選庫失敗");
mysql_query("SET NAMES utf8");

// 1. 取得所有主題文 (親文章)
$sql = "SELECT * FROM bbsrow WHERE bbsrow_parentid IS NULL ORDER BY bbsrow_posttime DESC";
$mainResult = mysql_query($sql, $conn);

// 2. 逐筆顯示主題文及其回覆樹
while ($main = mysql_fetch_assoc($mainResult)) {
    echo "
"; echo "

{$main['bbsrow_title']}

"; echo "

作者: {$main['bbsrow_auth']} | 時間: {$main['bbsrow_posttime']}

"; echo "
" . nl2br(htmlspecialchars($main['bbsrow_content'])) . "
"; // 顯示回覆樹 if ($main['bbsrow_returncount'] > 0) { showChildren($main['bbsrow_id']); } echo "

"; } // 3. 分頁邏輯 (簡易版) $perPage = 10; $page = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1; $offset = ($page - 1) * $perPage; // ... 修改主題文查詢加 LIMIT $offset, $perPage // ... 計算總頁數輸出分頁連結 ?>

效能優化與改進方向

問題解決方案
遞迴查詢 N+1 問題 (每層一個 SELECT)一次查詢所有資料,PHP 端建立樹狀陣列 (父ID 分組),單次遍歷輸出
深層回覆遞迴深度過大導致堆疊溢位改用迭代 + 陣列堆疊模擬遞迴,或限制最大回覆層數 (如 10 層)
bbsrow_returncount 需手動維護使用 Trigger 或應用層寫入時同步更新
舊版 mysql_* 函數已棄用改用 mysqli 或 PDO 預備陳述式

現代化重構範例 (mysqli + 單查詢建樹)

$sql = "SELECT * FROM bbsrow WHERE bbsrow_parentid IS NULL ORDER BY bbsrow_posttime DESC LIMIT ?, ?";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param("ii", $offset, $perPage);
$stmt->execute();
$threads = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);

// 一次撈取所有回覆
$allReplies = $mysqli->query("SELECT * FROM bbsrow WHERE bbsrow_parentid IS NOT NULL ORDER BY bbsrow_parentid, bbsrow_posttime")
                     ->fetch_all(MYSQLI_ASSOC);

// PHP 端建樹
$children = [];
foreach ($allReplies as $r) $children[$r['bbsrow_parentid']][] = $r;

function renderTree($parentId, $depth, $children) {
    if (!isset($children[$parentId])) return;
    echo "
    "; foreach ($children[$parentId] as $r) { echo "
  • " . str_repeat("→", $depth) . htmlspecialchars($r['bbsrow_title']) . "..."; renderTree($r['bbsrow_id'], $depth+1, $children); echo "
  • "; } echo "
"; } foreach ($threads as $t) { echo "

" . htmlspecialchars($t['bbsrow_title']) . "

"; renderTree($t['bbsrow_id'], 0, $children); }
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved