早期 PHP 開發常將 HTML 以長字符串形式硬編碼在代碼中,維護極其困難。本文介紹一個基於「標記替換」思想的模板類 TCreateHTML,通過在模板文件中定義特殊標記,實現邏輯與視圖的初步分離。
<!--##名稱##-->,結束標記 <!--@@名稱@@--><?php
// TCreateHTML.class.php
// 作者:sharetop | email: ycshowtop@21cn.com
// --- 輔助函數 ---
function isbegin($str) {
return (bool)preg_match("/<!--##[a-zA-Z]+##-->/", $str);
}
function isfinish($str) {
return (bool)preg_match("/<!--@@[a-zA-Z]+@@-->/", $str);
}
function getname($str) {
$tmp = explode("##", $str);
return $tmp[1] ?? '';
}
// --- 核心類 ---
class TCreateHTML {
var $HTemplate; // 模板文件路徑
var $FileName; // 輸出文件路徑
var $ModiString = []; // 標記名 => 替換內容
// 構造函數:指定模板文件
function TCreateHTML($tmplate) {
$this->HTemplate = $tmplate;
}
// 設置輸出文件名
function SetHTML($filename) {
$this->FileName = $filename;
}
// 註冊標記替換內容
function EditableBlock($name, $replace) {
$this->ModiString[$name] = $replace;
}
// 執行生成
function WriteHtml() {
$fc = file($this->HTemplate); // 按行讀取
$fp = fopen($this->FileName, "w");
$k = count($fc);
$begin = false;
$first = false;
$tag = "";
for ($i = 0; $i < $k; $i++) {
// 遇到開始標記
if (isbegin($fc[$i])) {
fputs($fp, $fc[$i]); // 保留標記行
$begin = true;
$first = true;
$tag = getname($fc[$i]);
continue;
}
// 遇到結束標記
if (isfinish($fc[$i])) {
fputs($fp, $fc[$i]);
$begin = false;
$first = false;
$tag = "";
continue;
}
// 標記區塊內:第一行替換,其餘清空
if ($begin == true) {
if ($first == true) {
$fc[$i] = $this->ModiString[$tag] . " ";
$first = false;
} else {
$fc[$i] = "";
}
}
fputs($fp, $fc[$i]);
}
fclose($fp);
}
}
?>
模板文件 template.htm:
<html>
<head><title><!--##title##--></title></head>
<body>
<h1><!--##title##--><!--@@title@@--></h1>
<div><!--##content##--><!--@@content@@--></div>
</body>
</html>
PHP 腳本:
<?php
require_once 'TCreateHTML.class.php';
$html = new TCreateHTML('template.htm');
$html->SetHTML('output.html');
$html->EditableBlock('title', '我的博客標題');
$html->EditableBlock('content', '<p>這是動態生成的內容...</p>');
$html->WriteHtml();
echo "靜態頁面已生成:output.html";
?>
| 優點 | 缺點 |
|---|---|
| 零依賴,純 PHP 實現 | 僅支持簡單變量替換,無邏輯控制(循環、條件) |
| 模板為純 HTML,設計師友好 | 標記語法較繁瑣,需成對編寫啟動/結束標記 |
| 理解成本極低,適合小項目 | 無緩存機制,高頻生成性能一般 |
| 輸出靜態文件,減輕服務器壓力 | 異常處理缺失(文件不存在、權限不足等) |
preg_replace_callback 替換行讀取,支持巢狀標記<!--##loop:list##-->...<!--@@loop:list@@-->雖然這個類在今天看較為原始,但它展示了「模板分離」的核心思想:視圖模板作為靜態骨架,動態數據通過標記注入。這正是所有現代模板引擎的共同祖先。