靜態頁生成能大幅降低資料庫查詢壓力,提升頁面載入速度。本文展示一套輕量級實作:使用 Apache mod_rewrite 判斷靜態檔是否存在,不存在時觸發 PHP 動態生成並寫入檔案,後續請求直接由 Web Server 服務靜態檔。
RewriteCond %{REQUEST_FILENAME} !-f)。
/Test/
├── .htaccess # 重寫規則
├── news.php # 文章列表頁(動態)
├── getnews.php # 靜態頁生成觸發器
├── newsDetail.php # 文章內容模板(動態生成)
└── html/ # 靜態頁輸出目錄(需可寫入權限)
└── news_3.html # 生成範例
RewriteEngine On
# 首頁重寫
RewriteRule ^index.html$ /news.php [L]
# 靜態頁不存在時重寫至生成腳本
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^html/news_([0-9]+).html$ getnews.php?id=$1 [L]
關鍵點:RewriteCond %{REQUEST_FILENAME} !-f 只有當請求的檔案**不存在**時才觸發後續 RewriteRule,避免生成後再次觸發重寫造成無限迴圈。
<?php
header("Content-Type: text/html; charset=gbk");
mysql_connect("localhost", "root", "");
mysql_query('SET NAMES gbk');
mysql_select_db("test");
$sql = "SELECT `id`, `title` FROM `arc` ORDER BY `id` DESC";
$rs = mysql_query($sql);
while ($row = mysql_fetch_array($rs)) {
// 連結指向靜態頁 URL
echo "<a href='/Test/html/news_{$row['id']}.html'>{$row['title']}</a><br>";
}
?>
<?php
$id = $_GET['id'];
$root = $_SERVER['DOCUMENT_ROOT'];
$filename = "news_{$id}.html";
$file = $root . "/Test/html/" . $filename;
// 1. 開啟輸出緩衝
ob_start();
// 2. 包含內容模板(會輸出 HTML 到緩衝區)
include($root . "/Test/newsDetail.php");
// 3. 取得緩衝內容並寫入檔案
$content = ob_get_contents();
file_put_contents($file, $content);
// 4. 結束緩衝並輸出給瀏覽器(首次請求直接看到內容)
ob_end_flush();
?>
<?php
header("Content-Type: text/html; charset=gbk");
if (!isset($_GET['id'])) {
header("Location: https://127.0.0.1/Test/html/news_failed.html");
exit();
}
$id = $_GET['id'];
mysql_connect("localhost", "root", "");
mysql_query('SET NAMES gbk');
mysql_select_db("test");
$sql = "SELECT `news` FROM `arc` WHERE `id`=$id";
$rs = mysql_query($sql);
while ($row = mysql_fetch_array($rs)) {
echo $row['news']; // 直接輸出文章內容
}
?>
用戶請求 /Test/html/news_3.html
↓
Apache 檢查 news_3.html 是否存在
↓
存在 → 直接返回靜態檔(結束)
不存在 → RewriteRule 重寫至 getnews.php?id=3
↓
getnews.php 執行:
1. ob_start()
2. include newsDetail.php → 查詢 DB → 輸出 HTML 到緩衝
3. ob_get_contents() → file_put_contents(news_3.html)
4. ob_end_flush() → 返回 HTML 給用戶
↓
下次請求 → Apache 直接服務 news_3.html
file_exists() 判斷並 header('Location: ...') 導向,會導致重寫規則再次匹配觸發生成腳本,形成迴圈。解決:將「檔案存在性判斷」交給 Apache RewriteCond !-f。fopen() + fwrite(),後改用 ob_* + file_put_contents(),效率提升約 20 倍。html/ 目錄需給 PHP 進程寫入權限(Linux: chmod 777 或設定擁有者為 www-data)。news_{id}.html 或建立後台「重新生成」功能。list_1.html, list_2.html。「Apache 判斷檔案存在性 + PHP 動態生成寫檔」是經典且高效的靜態化架構。核心在於將「存在性檢查」下沉到 Web Server 層,避免 PHP 進程啟動與迴圈問題,同時利用 ob_* 高效捕獲輸出。此模式易於理解、部署簡單,適合中小型內容型網站。