設計目標
- 極簡依賴,無需 Composer,單文件即用。
- 支持變量輸出
<{$var}>。
- 模板編譯緩存:模板修改後自動重新編譯。
- 編譯為原生 PHP 代碼,執行效率高。
核心代碼
<?php
class MyTpl {
private $template_dir;
private $compile_dir;
private $tpl_vars = [];
public function __construct($template_dir = "./templates", $compile_dir = "./templates_c") {
$this->template_dir = rtrim($template_dir, '/') . '/';
$this->compile_dir = rtrim($compile_dir, '/') . '/';
}
public function assign($tpl_var, $value = null) {
if ($tpl_var !== '') {
$this->tpl_vars[$tpl_var] = $value;
}
}
public function display($fileName) {
$tplFile = $this->template_dir . $fileName;
if (!file_exists($tplFile)) {
return false;
}
$comFileName = $this->compile_dir . "com_" . $fileName . ".php";
// 模板文件比編譯文件新,或編譯文件不存在 → 重新編譯
if (!file_exists($comFileName) || filemtime($comFileName) < filemtime($tplFile)) {
$content = file_get_contents($tplFile);
$repContent = $this->tpl_replace($content);
file_put_contents($comFileName, $repContent);
}
// 引入編譯後的 PHP 文件,變量已在 $this->tpl_vars 中
include $comFileName;
}
private function tpl_replace($content) {
// 匹配 <{$var}> 標簽,捕獲變量名
$pattern = '/\<\{\s*\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\s*\}\>/i';
$replacement = '<?php echo $this->tpl_vars["${1}"]; ?>';
return preg_replace($pattern, $replacement, $content);
}
}
?>
使用範例
模板文件 templates/index.tpl
<!DOCTYPE html>
<html>
<head><title><{$title}></title></head>
<body>
<h1><{$title}></h1>
<p><{$content}></p>
<ul>
<li>用戶: <{$user.name}></li>
<li>郵箱: <{$user.email}></li>
</ul>
</body>
</html>
業務代碼
<?php
require 'MyTpl.php';
$tpl = new MyTpl(__DIR__.'/templates', __DIR__.'/templates_c');
$tpl->assign('title', '歡迎使用 MyTpl');
$tpl->assign('content', '這是一個極簡模板引擎演示。');
$tpl->assign('user', ['name' => '張三', 'email' => 'zhangsan@example.com']);
$tpl->display('index.tpl');
?>
編譯後文件 templates_c/com_index.tpl.php
<!DOCTYPE html>
<html>
<head><title><?php echo $this->tpl_vars["title"]; ?></title></head>
<body>
<h1><?php echo $this->tpl_vars["title"]; ?></h1>
<p><?php echo $this->tpl_vars["content"]; ?></p>
<ul>
<li>用戶: <?php echo $this->tpl_vars["user"]; ?></li>
<li>郵箱: <?php echo $this->tpl_vars["user"]; ?></li>
</ul>
</body>
</html>
擴展方向
- 增加
{if} {foreach} {include} 等控制結構編譯。
- 支持修飾符:
<{$var|escape}>、<{$var|date:'Y-m-d'}>。
- 編譯階段進行語法檢查、安全過濾(禁用危險函數)。
- 引入命名空間、Composer 自動加載、單元測試。
安全提示
- 模板編譯為 PHP 直接執行,嚴禁允許用戶編寫/上傳模板文件,否則等同於任意代碼執行漏洞。
- 生產環境建議關閉錯誤顯示,啟用 OPcache 加速編譯文件載入。