靜態化是高流量網站常用優化手段:將動態頁面預先生成靜態 HTML/TXT,減輕資料庫與 PHP 處理壓力。本文提供完整批量生成腳本,涵蓋資料庫連線、模板讀取、佔位符替換、檔案寫入與資源釋放。
conn.php<?php
// conn.php
$host = '127.0.0.1';
$user = 'db_user';
$pass = 'db_pass';
$dbname = 'my_database';
$charset = 'utf8mb4';
$mysqli = new mysqli($host, $user, $pass, $dbname);
if ($mysqli->connect_errno) {
die("Connect failed: " . $mysqli->connect_error);
}
$mysqli->set_charset($charset);
// 供其他腳本 require 後直接使用 $mysqli
template.html<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{title}</title>
</head>
<body>
<h1>{title}</h1>
<div class="content">{content}</div>
<p class="meta">發布時間:{pub_time}</p>
</body>
</html>
gen_html.php<?php
require_once 'conn.php';
$outputDir = __DIR__ . '/html';
if (!is_dir($outputDir)) mkdir($outputDir, 0755, true);
// 讀取模板一次
$template = file_get_contents(__DIR__ . '/template.html');
if ($template === false) die('模板讀取失敗');
// 查詢需生成的文章
$sql = "SELECT id, title, content, created_at FROM articles WHERE status = 1";
$res = $mysqli->query($sql);
if (!$res) die("Query failed: " . $mysqli->error);
$success = $fail = 0;
while ($row = $res->fetch_assoc()) {
$id = (int)$row['id'];
$file = $outputDir . "/{$id}.html";
// 替換佔位符
$html = str_replace(
['{title}', '{content}', '{pub_time}'],
[$row['title'], $row['content'], $row['created_at']],
$template
);
// 寫入檔案 (LOCK_EX 避免並發衝突)
if (file_put_contents($file, $html, LOCK_EX) !== false) {
$success++;
} else {
$fail++;
error_log("生成失敗: $file");
}
}
$res->free();
$mysqli->close();
echo "完成:成功 $success,失敗 $fail\n";
gen_txt.php<?php
require_once 'conn.php';
$outputDir = __DIR__ . '/txt';
if (!is_dir($outputDir)) mkdir($outputDir, 0755, true);
$sql = "SELECT id, title, content FROM articles WHERE status = 1";
$res = $mysqli->query($sql);
while ($row = $res->fetch_assoc()) {
$id = (int)$row['id'];
$file = $outputDir . "/{$id}.txt";
// 簡單格式:標題 + 換行 + 內容 (去除 HTML 標籤)
$text = $row['title'] . "\n\n" . strip_tags($row['content']);
file_put_contents($file, $text, LOCK_EX);
}
$res->free();
$mysqli->close();
echo "TXT 生成完成\n";
| 需求 | 方案 | 關鍵點 |
|---|---|---|
| 大量資料 (10萬+) 避免記憶體爆炸 | 使用 mysqli::use_result() 或 PDO fetch() 游標模式 | 不一次性載入所有行,逐行處理 |
| 模板邏輯複雜 (判斷、迴圈、繼承) | 引入模板引擎:Twig, Blade, Smarty | 編譯快取、語法豐富、安全過濾 |
| 生成後自動部署到 CDN/靜態伺服器 | 腳本結束後呼叫 rsync、aws s3 sync、FTP 上傳 | 結合 CI/CD 流程 |
| 增量生成 (只更新變更文章) | 資料表加 updated_at、last_generated_at,查詢時過濾 | 避免全量重建浪費 IO |
| 多進程並行加速 | pcntl_fork 或 GuzzleHttp\Pool 非同步併發 | Windows 用 popen 啟動多個 CLI 進程 |
| URL 重寫對應 | 生成時同步產出 Nginx rewrite map 或資料庫路由表 | 前端訪問 /article/123 映射到 /html/123.html |
> /var/log/gen_html.log 2>&1
# Windows 任務排程器
# 程式: C:\php82\php.exe
# 參數: C:\www\scripts\gen_html.php
# 觸發: 每日/每小時
md5($title . $id),避免使用者控制的標題直接做檔名 (路徑遍歷風險)。str_replace,必須用沙箱模板引擎 (Twig Sandbox)。disk_free_space(),空間不足報警停止。