1. 程式人生 > >ThinkPHP 模板解析流程,研究筆記。

ThinkPHP 模板解析流程,研究筆記。

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()方法,其他的不管。

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;
    }
簡單解釋下 $this->tVar 是一個數組,當你$this->assign('a','b')的時候,就會自動新增$this->tVar['a']='b',然後通過extract()函式將陣列轉化為獨立變數,即$a='b';這隻在PHP原生模板時生效,而我們常規情況下是 else{ 之後的過程,也就是

$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方法解析模板: