寫一個迷你版Smarty模板引擎,對認識模板引擎原理非常好(附代碼)


  前些時間在看創智博客韓順平的Smarty模板引擎教程,再結合自己跟李炎恢第二季開發中CMS系統寫的tpl模板引擎。今天就寫一個迷你版的Smarty引擎,雖然說我並沒有深入分析過Smarty的源碼,但是對模板引擎的原理,還是有深刻的理解的。如果有什么還需要改進的地方,記得提出來。

 

一、什么是Smarty模板引擎:

  Smarty是一個使用PHP寫出來的模板引擎,是目前業界最著名的PHP模板引擎之一。它分離了邏輯代碼和外在的內容,提供了一種易於管理和使用的方法,用來將原本與HTML代碼混雜在一起PHP代碼邏輯分離。簡單的講,目的就是要使PHP程序員同前端人員分離,使程序員改變程序的邏輯內容不會影響到前端人員的頁面設計,前端人員重新修改頁面不會影響到程序的程序邏輯,這在多人合作的項目中顯的尤為重要。(來自百度百科)

 

自己的理解是:

第一,有利於把前端開發與后台開發工作分離,利於分工合作;

第二,其緩存機制,有利於加快網站的訪問速度;

第三,模板標簽還可以一次編寫,到處調用,便利和簡潔性好;

 

二、下面就一起開發迷你版模板引擎吧

(1)首先先把已經做好的模板引擎給大家看一看,先使用,再開發

① 迷你版Smarty模板引擎目錄結構如下:

 

源代碼里面有很詳細的說明,請看下面

 

① 要開發一個模板引擎,最主要的有兩個類,分別是模板引擎入口類和模板解析類。

A.首先創建MiniSmarty目錄,然后新建一個文件名為MiniSmarty.class.php

其代碼如下:

/**
 * MiniSmarty模板引擎
 * @link http://www.cnblogs.com/isuhua/
 * @author 華仔_suhua <weibo.com/suhua123>
 * @package MiniSmarty
 * @version 0.0.0.1
 */
class MiniSmarty {
    //模板文件
    public $template_dir = 'templates';
    //編譯文件
    public $compile_dir = 'templates_c';
    //緩存文件
    public $cache_dir = 'cache';
    //模板變量
    public $_tpl_var = array();
    //是否開啟緩存
    public $caching = false;
    
    public function __construct() {
        $this->checkDir();
    }
    
    //檢查目錄是否建好
    private function checkDir() {
        if (!is_dir($this->template_dir)) {
            exit('模板文件目錄templates不存在!請手動創建');
        }
        if (!is_dir($this->compile_dir)) {
            exit('編譯文件目錄templates_c不存在!請手工創建!');
        }
        if (!is_dir($this->cache_dir)) {
            exit('緩存文件目錄'.$this->cache_dir.'不存在!請手工創建!');
        }
    }
    
    //模板變量注入方法
    public function assign($tpl_var, $var = null) {
        if (isset($tpl_var) && !empty($tpl_var)) {
            $this->_tpl_var[$tpl_var] = $var;
        } else {
            exit('模板變量名沒有設置好');
        }
    }
    
    //文件編譯
    public function display($file) {
        //模板文件
        $tpl_file  = $this->template_dir.'/'.$file;
        if (!file_exists($tpl_file)) {
            exit('ERROR:模板文件不存在!');
        }
        //編譯文件
        $parse_file = $this->compile_dir.'/'.md5($file).$file.'.php';
        
        //只有當編譯文件不存在或者是模板文件被修改過了
        //才重新編譯文件
        if (!file_exists($parse_file) || filemtime($parse_file) < filemtime($tpl_file)) {
            include 'smarty_compile.class.php';
            $compile = new Smarty_Compile($tpl_file);
            $compile->parse($parse_file);
        }
        
        //開啟了緩存才加載緩存文件,否則直接加載編譯文件
        if ($this->caching) {
            //緩存文件
            $cache_file = $this->cache_dir.'/'.md5($file).$file.'.html';
            //只有當緩存文件不存在,或者編譯文件已被修改過
            //重新生成緩存文件
            if (!file_exists($cache_file) || filemtime($cache_file) < filemtime($parse_file)) {
                //引入緩存文件
                include $parse_file;
                //緩存內容
                $content = ob_get_clean();
                //生成緩存文件
                if (!file_put_contents($cache_file, $content)) {
                    exit('緩存文件生成出錯!');
                }
            }
            //載入緩存文件
            include $cache_file;
        } else {
            //載入編譯文件
            include $parse_file;
        }
    }
}

 

 B.然后再新建一個MiniSmarty模板引擎解析器類文件:MiniSmarty_Compile.class.php

其代碼如下:

<?php
/**
 * MiniSmarty模板引擎
 * @link http://www.cnblogs.com/isuhua/
 * @author 華仔_suhua <weibo.com/suhua123>
 * @package MiniSmarty
 * @version 0.0.0.1
 */
class MiniSmarty_Compile {
    //模板內容
    private $content = '';
    
    //構造函數
    public function __construct($tpl_file) {
        $this->content = file_get_contents($tpl_file);
    }
    
    //解析普通變量,如把{$name}解析成$this->_tpl_var['name']
    public function parseVar() {
        $pattern = '/\{\$([\w\d]+)\}/';
        if (preg_match($pattern, $this->content)) {
            $this->content = preg_replace($pattern, '<?php echo \$this->_tpl_var["$1"]?>', $this->content);
        }
    }
    
    //這里可以自定義其他解析器...
    
    //模板編譯
    public function parse($parse_file) {
        //調用普通變量解析器
        $this->parseVar();
        //這里可以調用其他解析器...
        
        //編譯完成后,生成編譯文件
        if (!file_put_contents($parse_file, $this->content)) {
            exit('編譯文件生成出錯!');
        }
    }
}
?>

 

C.最后,還必須新建幾個目錄,分別是模板文件目錄templates、編譯文件目錄 template_c、緩存文件目錄cache。

如果你(ˇˍˇ) 想~一次性成功,就必須創建這幾個目錄,缺一不可。否則就會報錯,然后要求你手動創建。

 

D.來試試看吧,編寫demo.php,測試一下自定義的迷你版MiniSmarty模板引擎吧!

demo.php代碼如下:

    //引入模板引擎
    require 'MiniSmarty.class.php';
    //實例化模板類
    $minismarty = new MiniSmarty();
    //緩存開關
    $minismarty->caching = true;
    
    //定義變量
    $webname = '迷你版Smarty測試';
    $author = 'suhua';
    $title = '這是一個測試標題';
    $content = '這是一段測試內容';
    
    //注入變量
    $minismarty->assign('webname', $webname);
    $minismarty->assign('author', $author);
    $minismarty->assign('title', $title);
    $minismarty->assign('content', $content);
    
    //啟動編譯模板文件
    $minismarty->display('demo.tpl');

 

測試前,請先看一下template、template_c 以及cache目錄各自的狀態,請看下圖:

 

 E:打開瀏覽器,輸入http://localhost/MiniSmarty/demo.php,即可看到一下效果:

 

測試后,請再次看一下各目錄的狀態:

 在template_c目錄和cache目錄下都分別多了一個xxxx.tpl.php和xxx.tpl.html文件,為什么呢?

答:這就是模板引擎非常重要的一個作用,編譯文件並生成靜態文件。對於如何實現的,這里不做解析,源碼已經給出,看看就懂。

 

---->至此表示自己開發的一個迷你版Smarty模板引擎成功!*\(^v^)/*

 

再次測試一下緩存功能是否生效了,首先修改demo.php中的代碼,改動如下:

把 $author = 'suhua'; 修改為 $author = 'xiwang';

改動過后,記得保存,然后再次刷新頁面,看出現什么狀況了?

 

結果是:沒有任何變化!這就正常了否則緩存功能沒有實現。

???為什么沒有任何變化呢

答:原因是我們在demo.php中開啟了緩存功能

//緩存開關
$minismarty->caching = true;

請看代碼。下面這段代碼是MiniSmarty.class.php里面的,下面就是根據你是否開啟緩存,決定是加載緩存文件還是編譯文件。因為這里開啟了,所以會直接加載緩存文件,所以就算你修改了原來的模板,依然沒變化。

        //開啟了緩存才加載緩存文件,否則直接加載編譯文件
        if ($this->caching) {
            //緩存文件
            $cache_file = $this->cache_dir.'/'.md5($file).$file.'.html';
            //只有當緩存文件不存在,或者編譯文件已被修改過
            //重新生成緩存文件
            if (!file_exists($cache_file) || filemtime($cache_file) < filemtime($parse_file)) {
                //引入緩存文件
                include $parse_file;
                //緩存內容
                $content = ob_get_clean();
                //生成緩存文件
                if (!file_put_contents($cache_file, $content)) {
                    exit('緩存文件生成出錯!');
                }
            }
            //載入緩存文件
            include $cache_file;
        } else {
            //載入編譯文件
            include $parse_file;
        }

如果我在demo.php中把緩存功能關了呢,結果會如何?

即改動如下:

//緩存開關
 $minismarty->caching = false; //關閉緩存功能

 

 此時,當你再次刷新頁面的時候,你會看到如下效果:

 此時,作者一欄改變了,這說明了模板引擎此時並沒有去加載緩存文件,而是直接加載了編譯文件。所以會出現該效果。上面的代碼也說明了這一點。

 

其他細節在源碼中都有較詳細的注釋,在這里就不多說了,說一下其原理。

 

 

★ MiniSmarty模板引擎原理:(非常重要)

其原理也比較簡單

① 首先模板引擎會加載模板文件templates/demo.tpl,然后調用模板編譯類對其進行編譯解析(說白了就是變量替換或者標簽替換),編譯后就會生成編譯文件xxxx.tpl.php;

② 然后判斷緩存是否開啟,來決定是否生成緩存文件。其生成過程是:直接把xxx.tpl.php編譯文件加載進來,然后再從緩沖區取出所有內容,清空緩沖區,把內容寫入到緩存文件中xxx.tpl.html文件。

③ 模板文件demo.tpl是一個同時具有html和引擎標簽的復合文件,編譯文件xxx.tpl.php是把引擎標簽替換成php代碼,是具有php和html標簽的復合文件,緩存文件xxx.tpl.html文件就是一個純html的靜態文件;

 

至此,迷你版MiniSmarty模板引擎開發完成!

其中,如果還有其他不好的地方,希望各位指出!謝謝。

 

 最后附上:MiniSmarty源碼.rar (點擊即可下載)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM