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

Smarty 批量生成靜態 HTML 實戰:fetch + 文件寫入實現 CMS 靜態化

     編輯:PHP 相關知識

場景

文章詳情頁、列表頁等高頻讀、低頻寫頁面,生成純靜態 HTML 可:

  • 極致性能:Nginx 直接服務靜態文件,無 PHP/FPM 開銷。
  • 抗高併發:靜態文件可直接 CDN 分發。
  • SEO 友好:搜索引擎抓取穩定、快速。

核心思路

1. 後台發布/定時任務觸發
2. 遍歷數據 (文章 ID 列表)
3. $smarty->assign('article', $articleData)
4. $html = $smarty->fetch('article.tpl')  // 獲取渲染字符串,不輸出
5. file_put_contents("/html/article/{$id}.html", $html)
6. (可選) 刷新 CDN 緩存 / 推送搜索引擎

Smarty 擴展:MakeHtmlFile 方法

<?php
// 放入 Smarty 類或繼承類中
public function MakeHtmlFile(string $filePath, string $content): bool {
    // 確保目錄存在
    $dir = dirname($filePath);
    if (!is_dir($dir)) {
        mkdir($dir, 0755, true);
    }
    // 原子寫入:臨時文件 + rename (防止讀到半寫文件)
    $tmpFile = $filePath . '.tmp.' . uniqid();
    if (file_put_contents($tmpFile, $content, LOCK_EX) === false) {
        return false;
    }
    return rename($tmpFile, $filePath);
}
?>

批量生成腳本 generate_html.php

<?php
require_once 'config.php';
require_once 'init.php'; // 初始化 $smarty, $db

// 1. 獲取需生成的文章 ID 列表 (可加 where 条件、分批)
$sql = "SELECT id FROM articles WHERE status = 1 AND is_static = 1";
$ids = $db->getCol($sql); // 返回一維陣列 [1, 5, 12, ...]

echo "Start generating " . count($ids) . " articles...\n";

foreach ($ids as $id) {
    // 2. 獲取單篇文章完整數據
    $article = $db->getRow("SELECT * FROM articles WHERE id = ?", [$id]);
    if (!$article) continue;

    // 3. 賦值模板變量 (注意:模板中統一用 $article 訪問)
    $smarty->assign('article', $article);

    // 4. 渲染獲取 HTML 字符串
    // fetch 參數:模板文件、cache_id、compile_id、display=false(返回字符串)
    $html = $smarty->fetch('article.tpl', null, null, false);

    // 5. 寫入靜態文件
    $filePath = "/var/www/html/article/{$id}.html";
    if ($smarty->MakeHtmlFile($filePath, $html)) {
        echo "[$id] OK\n";
    } else {
        echo "[$id] FAILED\n";
    }

    // 6. 可選:清除該文章相關緩存
    $smarty->clearCache('article.tpl', $id);
}

// 7. 批量生成列表頁 (分頁)
$pageSize = 20;
$total = $db->getOne("SELECT COUNT(*) FROM articles WHERE status=1");
$pages = ceil($total / $pageSize);
for ($p = 1; $p <= $pages; $p++) {
    $list = $db->getAll("SELECT * FROM articles WHERE status=1 ORDER BY id DESC LIMIT ?, ?", [($p-1)*$pageSize, $pageSize]);
    $smarty->assign('articles', $list);
    $smarty->assign('page', $p);
    $smarty->assign('totalPages', $pages);
    $html = $smarty->fetch('list.tpl', null, null, false);
    $filePath = "/var/www/html/list/page_{$p}.html";
    $smarty->MakeHtmlFile($filePath, $html);
}

echo "All done.\n";
?>

模板文件示例

templates/article.tpl

```html {$article.title}

{$article.title}

作者:{$article.author} | 時間:{$article.created_at|date_format:'%Y-%m-%d %H:%M'}
{$article.content}
{include file='footer.tpl'} ```

templates/list.tpl

```html 文章列表 - 第 {$page} 頁
    {foreach $articles as $a}
  • {$a.title} {$a.created_at|date_format:'%m-%d'}
  • {/foreach}
```

Nginx 配置:優先服務靜態文件

server {
    root /var/www/html;
    index index.html index.php;

    location / {
        # 嘗試直接服務靜態文件,不存在則 fallback 到 PHP
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

進階優化策略

策略實現收益
增量生成只重新生成變更的文章 + 受影響列表頁減少 90%+ I/O
異步隊列發布後推送任務到 Redis/RabbitMQ,Worker 消費生成不阻塞用戶請求、削峰填谷
多進程並行PCNTL fork 或 GNU parallel 分批跑利用多核,縮短總耗時
CDN 預熱生成後調用 CDN API 刷新/預熱 URL首屏秒開
模板片段緩存Smarty {block} + cache_id 緩存公共片段 (頭部、側邊欄)減少重複渲染

總結

Smarty 批量靜態化核心:**fetch() 獲取渲染字符串 + file_put_contents() 原子寫入**。關鍵點:模板變量統一命名 (如 $article)、目錄預創建、臨時文件重命名、Nginx try_files 優先靜態。**生產環境務必上異步隊列 + 增量生成 + CDN 預熱**。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved