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

PHP 生成靜態 HTML 頁面完整方案:ob_start 緩衝捕獲、批量生成、分頁處理、目錄自動創建

     編輯:PHP 相關知識

PHP 生成靜態 HTML 頁面完整方案:ob_start 緩衝捕獲、批量生成、分頁處理、目錄自動創建

動態頁靜態化能大幅降低數據庫壓力、提升首屏速度、利於 SEO。本文提供一套**生產可用**的批量生成腳本:模板渲染捕獲、按年月分目錄存儲、分批次生成避免超時、進度顯示與完成提醒。

一、核心原理:輸出緩衝

<?php
// 1. 開啟緩衝
ob_start();

// 2. 執行動態頁邏輯 (包含模板、數據查詢、echo 輸出)
include 'moban.php?id=123'; // 模板文件內部可用 $id 變量

// 3. 獲取緩衝內容並關閉緩衝
$html = ob_get_contents();
ob_end_clean();

// 4. 寫入文件
file_put_contents('html/202401/item_123.html', $html);
優於 file_get_contents('https://domain/moban.php?id=123'):無需 HTTP 開銷、可直接傳遞變量、不受防火牆/域名解析影響。

二、完整批量生成腳本 make.php

<?php
set_time_limit(0);          // 無限制執行時間
ini_set('memory_limit', '512M');

require 'config/db.php';    // 數據庫連接 $pdo
require 'Pager.php';        // 分頁類

// 參數:每批次條數 t、起始頁 pg
$pageSize = isset($_GET['t']) ? max(1, (int)$_GET['t']) : 200;
$pageNum  = isset($_GET['pg']) ? max(1, (int)$_GET['pg']) : 1;

// 總數
$total = $pdo->query("SELECT COUNT(*) FROM carsell")->fetchColumn();
$pager = new Pager($total, $pageSize);
$pager->setPage($pageNum);

// 當前批次數據
$offset = ($pageNum - 1) * $pageSize;
$stmt = $pdo->prepare("SELECT * FROM carsell ORDER BY id DESC LIMIT ?, ?");
$stmt->execute([$offset, $pageSize]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

// 開始生成
echo "<h2>第 {$pageNum} 批生成中... (共 {$pager->pageCount} 批)</h2>";
echo "<textarea style='width:100%;height:400px'>";

foreach ($rows as $row) {
    $id = $row['id'];
    
    // 1. 捕獲模板輸出
    ob_start();
    // 模板內可直接使用 $row 變量
    include __DIR__ . '/moban.php';
    $html = ob_get_clean();

    // 2. 目標路徑:html/年月/item_id.html
    $ym = date('Ym', strtotime($row['put_date']));
    $dir = __DIR__ . "/html/{$ym}";
    if (!is_dir($dir)) {
        mkdir($dir, 0755, true);
        echo "[DIR] Created: {$dir}\n";
    }
    $file = "{$dir}/item_{$id}.html";

    // 3. 寫入
    if (file_put_contents($file, $html) !== false) {
        echo "[OK] {$file}\n";
    } else {
        echo "[FAIL] {$file}\n";
    }
}
echo "</textarea>";

// 4. 自動跳轉下一批或完成
if ($pageNum < $pager->pageCount) {
    $next = $pageNum + 1;
    echo "<script>setTimeout(()=>location.href='make.php?t={$pageSize}&pg={$next}', 500);</script>";
} else {
    echo "<script>alert('所有 {$total} 條靜態頁生成完成!');</script>";
}

三、模板文件 moban.php 示例

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title><?= htmlspecialchars($row['title']) ?></title>
</head>
<body>
    <h1><?= htmlspecialchars($row['title']) ?></h1>
    <p>發布時間: <?= date('Y-m-d H:i', strtotime($row['put_date'])) ?></p>
    <div><?= $row['content'] ?></div>
</body>
</html>

四、分頁類 Pager.php 精簡版

<?php
class Pager {
    public $total, $pageSize, $pageCount, $currentPage;
    public function __construct(int $total, int $pageSize) {
        $this->total = $total;
        $this->pageSize = $pageSize;
        $this->pageCount = ceil($total / $pageSize);
    }
    public function setPage(int $page) {
        $this->currentPage = max(1, min($page, $this->pageCount));
    }
}

五、關鍵優化點

優化實現
避免內存爆炸單條處理 + ob_get_clean() 即時釋放,不累積大字符串
防止腳本超時分批次 (建議 200-500 條/批) + 前端 JS 自動跳轉下一批
目錄權限mkdir($dir, 0755, true) 遞歸創建,生產環境確保 PHP-FPM 用戶有寫權限
并發生成大數據量可用 pcntl_fork 或 Swoole 多進程并行,配合 Redis 隊列分發 ID
增量更新記錄 last_generate_time,僅重新生成更新過的記錄
CDN 刷新生成後調用 CDN API (如阿里云 RefreshObjectCaches) 預熱/刷新緩存

六、替代方案對比

方案優點缺點適用場景
ob_start + include (本文)零依賴、變量直接可用、性能高模板邏輯與 PHP 混合中小項目、現有 PHP 模板
Smarty fetch()模板分離、緩存編譯、插件豐富學習成本、額外依賴大型項目、團隊協作
Twig/Blade語法優雅、安全(自動轉義)、繼承塊需 Composer、框架綁定現代框架項目 (Laravel/Symfony)
靜態站點生成器 (Hugo/Jekyll/VitePress)極快、Markdown 寫作、Git 部署無動態數據庫查詢、學習曲線文檔站、博客、不頻繁更新內容

七、部署建議

  1. 將 make.php 放在**非 Web 可訪問目錄** (如 /data/scripts/),通過 CLI 定時任務觸發:0 2 * * * cd /data/scripts && php make.php t=500 pg=1 >/dev/null 2>&1。
  2. 2. 生成目錄 html/ 配置 Nginx 靜態資源服務:location /static/ { alias /data/scripts/html/; expires 30d; }。 3. 監控生成日志、失敗告警、磁盤空間 (預留 20%+)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved