| 维度 | 动态页面 | 静态页面 |
|---|---|---|
| 处理流程 | 请求 → PHP 解析 → 数据库查询 → 模板渲染 → 输出 HTML | 请求 → Web 服务器直接读取文件 → 输出 HTML |
| 服务器压力 | 高(CPU/内存/数据库连接) | 极低(仅静态文件 I/O) |
| 响应速度 | 较慢(百毫秒级) | 极快(毫秒级,可 CDN 缓存) |
| 实时性 | 强(每次请求最新数据) | 弱(需重新生成才能更新) |
| 适用场景 | 用户中心、购物车、实时数据、权限控制 | 文章详情、列表页、首页、商品详情、帮助文档 |
模板 = 含占位符的 HTML 文件。PHP 读取模板,用业务数据替换占位符,写入目标静态文件。
<html>
<head><title>{title}</title></head>
<body>
<h1>{title}</h1>
<div>{content}</div>
</body>
</html>
<?php
$title = 'PHP 静态页生成演示';
$content = '这是通过模板替换生成的静态页面内容。';
// 1. 读取模板
$tpl = file_get_contents('temp.html');
// 2. 替换占位符
$html = str_replace(['{title}', '{content}'], [$title, $content], $tpl);
// 3. 写入目标文件
$targetFile = 'article/2024/01/01/demo.html';
$dir = dirname($targetFile);
if (!is_dir($dir)) mkdir($dir, 0755, true);
$fp = fopen($targetFile, 'w');
if (!$fp) die("无法创建文件: $targetFile");
fwrite($fp, $html);
fclose($fp);
echo "静态页生成成功: $targetFile";
?>
articles,字段:id, title, slug, channel_id, created_at{article_list} 占位符index.html, index_2.html ...<?php
// 配置
$pageSize = 20;
$channelId = 1;
$tplFile = 'list_tpl.html';
$outDir = 'news/channel_1/';
// 1. 读取模板
$tpl = file_get_contents($tplFile);
// 2. 查询总数
$pdo = new PDO('mysql:host=localhost;dbname=cms', 'user', 'pass');
$total = $pdo->query("SELECT COUNT(*) FROM articles WHERE channel_id=$channelId")->fetchColumn();
$totalPages = ceil($total / $pageSize);
// 3. 循环生成每页
for ($page = 1; $page <= $totalPages; $page++) {
$offset = ($page - 1) * $pageSize;
$stmt = $pdo->prepare("SELECT title, slug FROM articles WHERE channel_id=? ORDER BY created_at DESC LIMIT ?, ?");
$stmt->execute([$channelId, $offset, $pageSize]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 4. 组装列表 HTML
$listHtml = '';
foreach ($rows as $row) {
$listHtml .= "<li><a href='/article/{$row['slug']}.html'>{$row['title']}</a></li>\n";
}
// 5. 替换模板
$pageHtml = str_replace('{article_list}', $listHtml, $tpl);
// 可再替换分页导航 {pager} 等
// 6. 确定输出文件名
$fileName = ($page === 1) ? 'index.html' : "index_$page.html";
$target = $outDir . $fileName;
// 7. 写入文件 (存在则覆盖)
if (file_exists($target)) unlink($target);
$fp = fopen($target, 'w');
fwrite($fp, $pageHtml);
fclose($fp);
echo "Generated: $target\n";
}
echo "分页静态页生成完成,共 $totalPages 页。";
?>
| 环节 | 要点 |
|---|---|
| 模板语法 | 简单用 str_replace;复杂逻辑(循环/判断)引入 Smarty、Blade、Twig 等模板引擎 |
| 文件写入 | 使用 fopen/w/fclose 或 file_put_contents (原子写入需 LOCK_EX + 临时文件重命名) |
| 目录权限 | 生成目录需 PHP 进程用户可写 (chown www:www、chmod 755) |
| 并发生成 | 大批量生成用队列 + 多 Worker 并行,避免单进程超时 |
| 更新策略 | 文章发布/修改/删除时触发增量重新生成相关页面 |
| CDN 刷新 | 生成完成后调用 CDN API 刷新对应 URL 缓存 |
若项目以内容发布为主、交互少,SSG 架构比动态 PHP + 定时生成静态页更简洁、性能更强、维护成本更低。