Smarty 是 PHP 經典模板引擎,核心機制是「模板編譯為 PHP 快取檔」。本文從零實作一個極簡版 MinSmarty,展示模板讀取、正則替換變數標籤、編譯快取、引入執行的完整流程,適合理解模板引擎底層原理或輕量專案直接使用。
<?php
class MinSmarty {
// 模板目錄
public $template_dir = "./templates/";
// 編譯快取目錄
public $compile_dir = "./templates_c/";
// 模板變數容器
protected $tpl_vars = [];
// 變數賦值
public function assign($tpl_var, $value = null) {
if ($tpl_var !== null) {
$this->tpl_vars[$tpl_var] = $value;
}
}
// 顯示模板(核心流程)
public function display($tpl_file) {
$tpl_path = $this->template_dir . $tpl_file;
$compile_path = $this->compile_dir . "com_" . $tpl_file . ".php";
if (!file_exists($tpl_path)) {
return false;
}
// 檢查是否需要重新編譯
if (!file_exists($compile_path) || filemtime($tpl_path) > filemtime($compile_path)) {
$content = file_get_contents($tpl_path);
// 核心正則:{$var} => tpl_vars['var']; ?>
$pattern = '/\{\s*\$([a-zA-Z_][a-zA-Z0-9_]*)\s*\}/i';
$replace = '<?php echo $this->tpl_vars["${1}"]; ?>';
$compiled = preg_replace($pattern, $replace, $content);
file_put_contents($compile_path, $compiled);
}
// 直接引入編譯後的 PHP 檔案執行
include_once($compile_path);
}
}
intro.php<?php
require_once "MinSmarty.class.php";
$title = "這裡是標題";
$content = "這裡是內容 111111";
$smarty = new MinSmarty();
$smarty->assign("title", $title);
$smarty->assign("content", $content);
$smarty->display("intro.tpl");
templates/intro.tpl<!DOCTYPE html>
<html xmlns="https://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>{$title}</title>
</head>
<body>
{$content}
</body>
</html>
templates_c/com_intro.tpl.php<!DOCTYPE html>
<html xmlns="https://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title><?php echo $this->tpl_vars["title"]; ?></title>
</head>
<body>
<?php echo $this->tpl_vars["content"]; ?>
</body>
</html>
{$variable},正則 /\{\s*\$([a-zA-Z_][a-zA-Z0-9_]*)\s*\}/i 支援大小寫、底線、數字。filemtime(),模板較新才重編譯。include_once 在 display() 作用域執行,$this 指向 MinSmarty 實例,故能存取 $this->tpl_vars。assign() 設定的變數,避免任意變數洩漏。{if}...{/if}, {foreach}...{/foreach} 需編譯為 PHP 流程控制結構。{$var|escape:'html'} 對應 htmlspecialchars()。{extends 'layout.tpl'} + {block name} 實現佈局復用。{cache lifetime=300} 輸出 HTML 直接快取。MinSmarty 雖簡陋,卻完整展示了「模板→編譯→快取→執行」的核心生命週期。理解此原理,不僅能自製輕量模板引擎,更能深入掌握 Smarty、Twig、Blade 等主流引擎的設計哲學,遇到編譯異常、快取失效等問題時也能快速定位根因。