ThinkPHP 模板解析流程,研究筆記。
$this->display();
來輸出帶有模板的檢視。
那麼就從這個方法入手。
1.Action.class.php 控制器基類
這是控制器基類,在這裡面找到display()方法。
protected function display($templateFile='',$charset='',$contentType='',$content='',$prefix='') {
$this->view->display($templateFile,$charset,$contentType,$content,$prefix);
}
可以看出,這裡實際上是呼叫 View檢視類的display()方法。
2.View.class.php 檢視類
public function display($templateFile='',$charset='',$contentType='',$content='',$prefix='') {
...
// 解析並獲取模板內容
$content = $this->fetch($templateFile,$content,$prefix);
// 輸出模板內容
$this->render($content,$charset,$contentType);
...
}
關鍵在於fetch()方法和render()方法,其他的不管。
簡單解釋下 $this->tVar 是一個數組,當你$this->assign('a','b')的時候,就會自動新增$this->tVar['a']='b',然後通過extract()函式將陣列轉化為獨立變數,即$a='b';這隻在PHP原生模板時生效,而我們常規情況下是 else{ 之後的過程,也就是public function fetch($templateFile='',$content='',$prefix='') { ...//沒有指定模板檔案的話,自動定位模板檔案,省略 // 頁面快取 ob_start(); ob_implicit_flush(0); if('php' == strtolower(C('TMPL_ENGINE_TYPE'))) { // 使用PHP原生模板 // 模板陣列變數分解成為獨立變數 extract($this->tVar, EXTR_OVERWRITE); // 直接載入PHP模板 empty($content)?include $templateFile:eval('?>'.$content); }else{ // 檢視解析標籤 $params = array('var'=>$this->tVar,'file'=>$templateFile,'content'=>$content,'prefix'=>$prefix); tag('view_parse',$params); } // 獲取並清空快取 $content = ob_get_clean(); // 內容過濾標籤 tag('view_filter',$content); // 輸出模板檔案 return $content; }
$params = array('var'=>$this->tVar,'file'=>$templateFile,'content'=>$content,'prefix'=>$prefix);
tag('view_parse',$params);
這兩行程式碼,$params是將一些變數組成一個數組,通過tag呼叫view_parse處的行為(在conf/tags.php中定義),該行為類是lib/behavior/ParseTemplateBehavior.class.php;
這個行為來解析檢視標籤。
3.ParseTemplateBehavior 模板解析核心行為
行為通過run()方法開始解析,而上面的$params作為引用引數傳遞到run(&$_data)中。即$_data=&$params,下面從run()方法分析。
篇幅關係,這裡就不打程式碼了。
大致流程如下:
檢測模板快取檔案是否存在並且有效,存在的話直接include它,如果不存在,則呼叫ThinkTemplate類下的fetch方法進行模板解析和編譯,將編譯結果寫入快取,並include快取檔案。
快取檔案就是將模板進行標籤替換後的一個PHP指令碼,include它的話就是輸出頁面了。
4. 模板的編譯
模板編譯函式位於ThinkTemplate.class.php中,方法是:protected function compiler($tmplContent){} 只有一個引數,就是讀取模板檔案的內容字串。
protected function compiler($tmplContent) {
//模板解析
$tmplContent = $this->parse($tmplContent);
// 還原被替換的Literal標籤
$tmplContent = preg_replace('/<!--###literal(\d+)###-->/eis',"\$this->restoreLiteral('\\1')",$tmplContent);
// 新增安全程式碼
$tmplContent = '<?php if (!defined(\'THINK_PATH\')) exit();?>'.$tmplContent;
if(C('TMPL_STRIP_SPACE')) {
/* 去除html空格與換行 */
$find = array('~>\s+<~','~>(\s+\n|\r)~');
$replace = array('><','>');
$tmplContent = preg_replace($find, $replace, $tmplContent);
}
// 優化生成的php程式碼
$tmplContent = str_replace('?><?php','',$tmplContent);
return strip_whitespace($tmplContent);
}
呼叫parse方法解析模板: