模板引擎本質是「讀取模板 → 解析語法 → 生成 PHP 代碼 → 執行輸出」。本文實現一個極簡版引擎,支援變量輸出 {$var}、編譯緩存(修改模板自動重編譯)、自定義定界符、目錄配置。
<?php
class Tpl {
private $template_dir = 'templates';
private $compile_dir = 'compiles';
private $left_delimiter = '{';
private $right_delimiter = '}';
private $tpl_vars = [];
// 變量賦值
public function assign($tpl_var, $tpl_value = null) {
if (is_array($tpl_var)) {
foreach ($tpl_var as $k => $v) $this->tpl_vars[$k] = $v;
} elseif ($tpl_var) {
$this->tpl_vars[$tpl_var] = $tpl_value;
}
}
// 編譯模板
private function fetch($tplFile, $comFile) {
if (!file_exists($comFile) || filemtime($tplFile) > filemtime($comFile)) {
$content = $this->tplReplace(file_get_contents($tplFile));
file_put_contents($comFile, $content);
}
}
// 正則替換 {$var} -> tpl_vars['var']; ?>
private function tplReplace($content) {
$left = preg_quote($this->left_delimiter, '/');
$right = preg_quote($this->right_delimiter, '/');
$pattern = '/'.$left.'\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)'.$right.'/i';
$replace = '<?php echo $this->tpl_vars[\'${1}\']; ?>';
return preg_replace($pattern, $replace, $content);
}
// 輸出
public function display($fileName) {
$tplFile = $this->template_dir . '/' . $fileName;
if (!file_exists($tplFile)) return $this->error('模板文件不存在');
$comFile = $this->compile_dir . '/' . md5($fileName) . '.php';
$this->fetch($tplFile, $comFile);
include $comFile;
}
// 配置修改
public function setConfigs(array $configs) {
foreach ($configs as $k => $v) if (property_exists($this, $k)) $this->$k = $v;
}
private function error($msg) { die($msg); }
}
?>
// templates/testTpl.html
<!DOCTYPE html>
<html><body>
{$name}:{$age}:{$message}
</body></html>
// test_tpl.php
require 'Tpl.php';
$tpl = new Tpl();
$tpl->assign(['name' => 'waited', 'age' => '100']);
$tpl->assign('message', 'this is a demo');
$tpl->display('testTpl.html');
// 輸出:waited:100:this is a demo
// 生成編譯文件:compiles/972fa4d270e295005c36c1dbc7e6a56c.php
{foreach $list as $item}、條件 {if $cond}。ob_start() 實現靜態化輸出。雖然生產環境建議使用 Smarty、Blade、Twig 等成熟引擎,但理解底層原理有助於排查模板相關疑難雜症。