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

PHP + XML 留言板完整實現:DOMDocument 操作、分頁與緩存

     編輯:PHP 綜合知識

架構設計

  • 數據存儲:單一 XML 文件(my_xmldb.xml),根節點 <Message>,每條記錄為 <Rows> 包含 Nickname、Content、Timer
  • 核心類:xmldb extends DOMDocument 封裝 CRUD 與分頁邏輯
  • 前端:簡單 HTML 表單 + CSS 佈局 + PHP 模板輸出

核心類代碼(_class.xmldb.inc.php)

<?php
class xmldb extends DOMDocument {
    private $xmldb;

    public function __construct($xmldbname) {
        $this->xmldb = $xmldbname;
        if (!file_exists($this->xmldb)) {
            $init = '<?xml version="1.0" encoding="utf-8"?><Message></Message>';
            $this->loadXML($init);
            $this->save($this->xmldb);
        } else {
            $this->load($this->xmldb);
        }
    }

    // 插入留言
    public function insert_message($nickname, $message) {
        $msgNode = $this->getElementsByTagName("Message")->item(0);
        $row = $this->createElement("Rows");

        $nick = $this->createElement("Nickname");
        $nick->appendChild($this->createTextNode($nickname));
        $row->appendChild($nick);

        $content = $this->createElement("Content");
        $content->appendChild($this->createTextNode($message));
        $row->appendChild($content);

        $timer = $this->createElement("Timer");
        $timer->appendChild($this->createTextNode(time()));
        $row->appendChild($timer);

        $msgNode->appendChild($row);
        $this->save($this->xmldb);
    }

    // 獲取節點總數
    public function get_node_length($tag) {
        return $this->getElementsByTagName($tag)->length;
    }

    // 分頁讀取列表
    public function get_message_list($start, $total, $pageSize) {
        $end = min($start + $pageSize, $total);
        $list = [];
        for ($i = $start; $i < $end; $i++) {
            $list[] = [
                'Nickname' => $this->getElementsByTagName("Nickname")->item($i)->nodeValue,
                'Content'  => $this->getElementsByTagName("Content")->item($i)->nodeValue,
                'Timer'    => $this->getElementsByTagName("Timer")->item($i)->nodeValue,
            ];
        }
        return $list;
    }

    // 通用分頁 HTML 生成
    public static function splitpage($pageAll, $page = 1, $urlFile = null, $pageParam = 'page', $pageAvg = 10) {
        $pageAvg--;
        $page = max(1, min((int)$page, $pageAll));
        $start = max(1, $page - (int)ceil($pageAvg / 2));
        $start = ($page + (int)ceil($pageAvg / 2) > $pageAll) ? $pageAll - $pageAvg : $start;
        $stop = min($start + $pageAvg, $pageAll);

        if (empty($urlFile)) $urlFile = $_SERVER['PHP_SELF'];
        $sep = strpos($urlFile, '?') ? '&' : '?';
        $query = http_build_query(array_diff_key($_GET, [$pageParam => '']));
        $base = $urlFile . $sep . $query . ($query ? '&' : '');

        $html = '';
        if ($page > 1) {
            $html .= "<a href='{$base}{$pageParam}=1'>首頁</a> ";
            $html .= "<a href='{$base}{$pageParam}=" . ($page - 1) . "'>上一頁</a> ";
        } else {
            $html .= "首頁 上一頁 ";
        }
        for ($i = $start; $i <= $stop; $i++) {
            $html .= ($i == $page) ? " $i " : " <a href='{$base}{$pageParam}=$i'>$i</a> ";
        }
        if ($page < $pageAll) {
            $html .= "<a href='{$base}{$pageParam}=" . ($page + 1) . "'>下一頁</a> ";
            $html .= "<a href='{$base}{$pageParam}=$pageAll'>尾頁</a>";
        } else {
            $html .= "下一頁 尾頁";
        }
        return $html;
    }
}
?>

前端調用(index.php)

<?php
require "_class.xmldb.inc.php";
$xmldb = new xmldb("./my_xmldb.xml");

if (isset($_POST['btnform1'])) {
    $xmldb->insert_message($_POST['nickname'], $_POST['content']);
}

$pageSize = 3;
$page = isset($_GET['page']) ? max(1, (int)$_GET['page']) : 1;
$total = $xmldb->get_node_length("Rows");
$pageCount = ceil($total / $pageSize);
$start = ($page - 1) * $pageSize;
$rows = $xmldb->get_message_list($start, $total, $pageSize);
?>
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>XML 留言板</title>
<style>#messagelist ul li{float:left;list-style:none;margin-right:20px;}</style></head>
<body>
<div id="messagelist">
<?php if ($rows): foreach ($rows as $v): ?>
    <ul>
        <li><?= htmlspecialchars($v['Nickname']) ?> <span>(<?= date('Y-m-d H:i', $v['Timer']) ?>)</span></li>
        <li><?= htmlspecialchars($v['Content']) ?></li>
    </ul><br>
<?php endforeach; endif; ?>
    <div><?= $xmldb::splitpage($pageCount, $page) ?></div>
</div>
<form method="post">
    暱稱: <input name="nickname" required><br>
    內容: <textarea name="content" required></textarea><br>
    <button name="btnform1">提交</button>
</form>
</body></html>

關鍵技術點

  1. DOMDocument:原生 XML 操作,無需第三方庫,支援 XPath、Schema 驗證。
  2. 原子寫入:save() 直接覆蓋文件,併發場景需加文件鎖(flock())或改用 SQLite。
  3. 分頁邏輯:splitpage() 靜態方法複用性強,自動保留其他 GET 參數。
  4. XSS 防護:輸出時統一 htmlspecialchars()。

擴展建議

  • 引入 SimpleXMLElement 或 XMLReader 處理大文件流式讀取
  • 加入驗證碼、敏感詞過濾、IP 限流
  • 遷移至 SQLite/MySQL 獲得併發與索引優勢
  • 前端接入 Vue/Alpine.js 實現無刷新提交
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved