??Smarty模板是業(yè)內最知名的PHP模板引擎之一审残,它實現了前后端的分離先紫,使PHP程序員和前端程序員各行其事衩茸,方便了多人的分工合作骗绕。從這里我們可以看出藐窄,模板引擎集中解決了代碼和表現分離這件事情。但是酬土,實現項目開發(fā)過程中荆忍,絕大多數情況下都會使用一款框架,當然每個PHP框架也都實現了自己的模板引擎诺凡。雖然我沒有精讀過Smarty模板的源碼东揣,但是我對使用過的框架源碼還有一定的基礎,所以對模板引擎原理有一定的理解腹泌。
模板語法
每個模板引擎都有一套自己約束的標簽寫法和解析規(guī)則嘶卧,如:Smarty模板默認定界符是"{ }
",ThinkPHP的默認定界符也是"{ }
"凉袱,Laravel模板默認定界符是"{{ }}
"芥吟,也有一些模板引擎使用"<{ }>
"作為默認的定界符。
處理流程
核心方法
模板類的主要實現assign
和display
兩個基礎方法专甩。
/**
* 模板變量賦值
* @access public
* @param mixed $name 變量名
* @param mixed $value 變量值
* @return $this
*/
public function assign($name, $value = '')
{
if (is_array($name)) {
$this->data = array_merge($this->data, $name);
} else {
$this->data[$name] = $value;
}
return $this;
}
/**
* 渲染模板文件
* @access public
* @param string $template 模板文件
* @param array $data 模板變量
* @return void
*/
public function display($template, $data = [])
{
// 判斷模板文件是否存在
if (!is_file($template))
{
exit('template not exists:' . $template);
}
$vars = array_merge($this->data, $data);
/**此處約省略1000000字*/
extract($vars, EXTR_OVERWRITE);
include $template;
}
模板解析類的主要實現parse
方法
/**
* 模板解析
* @access public
* @param string $content 要解析的模板內容
* @return true
*/
public function parse(&$content)
{
$content = preg_replace($pattern, $replacement, $content);
/**此處約省略1000000字*/
return true;
}
整體過程
- 請求從入口進來到達控制器钟鸵,實例化模板類,通過
assign
方法注入要展示的數據涤躲,通過display
方法綁定要展示的模板棺耍。 - 在模板類中引入相關配置,如:定界符种樱、模板路徑蒙袍、緩存類型、緩存路徑嫩挤、緩存時間害幅。實例化模板解析類,調起模板編譯方法岂昭。
- 在模板解析類中以现,通過緩存類型、編譯文件、更新模板文件否邑遏、過期時間等等判斷決定佣赖,是否生成
PHP+HTML
的混合文件,如果需要生成无宿,就調起parse
方法按約定的規(guī)則解析標簽內容茵汰,寫入編譯緩存文件枢里。 - 最后孽鸡,分解[
extract
]模板變量,載入[include
]緩存文件,顯示頁面數據栏豺。
由于我源出某派彬碱,不得不說某派的產品框架雖然有自己的模板引擎,并且號稱語法上基本忠于Smarty
模板奥洼,但是最后一步絕對使用eval
執(zhí)行編譯緩存文件巷疼,這與Smarty
模板不同。并且在爾后的模板類中將assign
和display
升級成為一個page("template.html", $pagedata);
方法灵奖,把參數注入改成由page
方法的第二個參數實現嚼沿。而 Smarty
模板最終實現方法如下:
這里HHVM_VERSION
常量全局沒有定義,所以它和其他框架一樣瓷患,默認使用include
載入緩存文件骡尽。這里不得不噴一下SHOPXC
的模板類,真是相當的丑陋和簡單擅编,連extract
都不愿意使用使用攀细,導致最后在模板中每個模板變量都得使用$output['xxx']
來接收。注:不是惡意評論SHOPXC
產品爱态,只是這種做法實現別扭谭贪。
綜上所述: 實現一款簡易的PHP模板引擎除了良好的OOP
基礎外,還需要掌握include, extract, is_file, file_exists, filemtime, file_get_contents, file_put_contents, preg_replace, str_replace, ob_start, ob_get_clean, eval, array_merge
等方法的使用锦担,其中正則表達式尤為重要俭识。
--END
--