1. 程式人生 > >PHP模板引擎Smarty(三)深入淺出之Smarty模板引擎工作機制(二)

PHP模板引擎Smarty(三)深入淺出之Smarty模板引擎工作機制(二)

轉自:http://www.cnblogs.com/hongfei/archive/2011/12/10/Smarty-two.html

接下來根據以下的Smarty模板引擎原理流程圖開發一個自己的模板引擎用於學習,以便加深理解。

Smarty模板引擎的原理,其實是這麼一個過程:
  把模板檔案編譯成php檔案,然後每次都去讀取下模板的修改時間,沒有修改就不編譯。然後include這個“編譯”後的PHP檔案。
  所謂編譯也就是模板用正則替換成含PHP程式碼的過程。
  實際上並不會每次請求都編譯,所以效能尚可。

   模板檔案和php程式檔案經過模板引擎的編譯後合成為一個檔案,即編譯後的檔案。

接下來,我們根據該原理流程寫一個簡單的模板引擎。。。。。。

  先貼上核心程式碼:

  Smarty.class.php檔案

<?php
    class Smarty{
        public $template_dir;//模板目錄
        public $compile_dir;//編譯目錄
        public $arr=array();//定義一個數組,用以存放assign中的第二個引數傳過來的值
        public function __construct($template_dir="../templates",$compile_dir="../templates_c"){
                $this->template_dir=$template_dir;//模板目錄
                $this->compile_dir=$compile_dir;  //編譯目錄
            }
        public function assign($content,$replacment=null){
                if($content!=""){                 //如果指定模板變數,才將要賦的值儲存到陣列中
                        $this->arr[$content]=$replacment;
                    }
            }
        public function display($page){
                $tplFile=$this->template_dir."/".$page;//讀取模板檔案,注意:如果模板目錄下還有子目錄,記得要寫完整,比如,$smarty->display('Default/index.tpl')
                if(!file_exists($tplFile)){
                        return;
                }
                $comFile=$this->compile_dir."/"."com_".$page.".php";
                $tplContent=$this->con_replace(file_get_contents($tplFile));//將smarty標籤替換為php的標籤
                file_put_contents($comFile,$tplContent);
                include $comFile;
        }
        public function con_replace($content){
                $pattern=array(
                    '/<{\s*\$([a-zA-Z_][a-zA-Z_0-9]*)\s*}>/i'
                );
                   $replacement=array(
                       '<?php echo $this->arr["${1}"] ?>'
                );
                    return preg_replace($pattern,$replacement,$content);
                }
        }
?>

Smarty.class.php程式碼解釋:

  • $template_dir  指定模板檔案的目錄
  • $compile_dir   指定編譯後的模板檔案的目錄
  • 建構函式 

    public function __construct($template_dir="../templates",$compile_dir="../templates_c")

    {                  

           $this->template_dir=$template_dir;

           $this->compile_dir=$compile_dir;

    }

    預設情況下,Smarty模板引擎將把templates目錄用於存放模板檔案,templates_c用於存放編譯後的檔案

  • assign($content,$replacment=null)函式的工作機制是將每次要傳遞給模板中的變數的值通過語句:$this->arr[$content]=$replacment;儲存到陣列中。  

     那為何要$replacement的值儲存到陣列中呢?

     其實內部操作是這麼一個流程:將$replacement值儲存到陣列--->讀取模板檔案(index.dwt,由display函式完成)--->將陣列中的值匹配給模板檔案中的變數(由con_replace()函式完成)--->將替換後的模板檔案寫入到編譯檔案中(com_index.dwt.php)--->輸出編譯後的PHP檔案

  • dispaly($page)函式接收一個引數,即要輸出的模板檔案(index.dwt)
    • 首先,將模板檔案的路徑賦給$tplFile($tplFile=$this->template_dir."/".$page)  
    • 判斷模板檔案是否存在,如果不存在,就沒必要載入了,直接return
    • 指定一個編譯檔案,以便存放替換變數後的模板檔案
    • 通過函式file_get_contents()讀取模板檔案,並通過函式conf_replace()替換掉模板中的smarty標籤
    • 將替換變數後的模板檔案通過file_put_contents()寫入到編譯檔案中
    • 將編譯後的檔案include進來,即可輸出編譯後的檔案
  • 函式con_replace($content)用於替換模板檔案(index.dwt)中的變數,即將php中的變數值賦給模板中的變數    
    • 通過一個可以匹配<{$title}>形式的正則表示式匹配模板檔案中的內容,並將匹配到的值替換為<?php echo $title?>的形式
    • 匹配到內容,並將替換後的內容返回
/*Smarty.ini.php檔案:用於完成初始化smarty的工作*/
<?php
    include "./libs/Smarty.class.php";
    $tpl=new Smarty();
    $tpl->template_dir="./Tpl";    
    $tpl->compile_dir="./Compile";
?>
<!--模板檔案-->
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title><{$title}></title>
</head>
<body>
<p>內容:<{$content}></p>
<p>作者:<{$auth}></p>
<p>網址:<{$website}></p>
</body>
</html>

/*index.php檔案*/
<?php
    include "./Smarty.ini.php";
    $title="深入淺出之Smarty模板引擎工作機制";    
    $content="Smarty模板引擎工作機制流程圖";
    $auth="MarcoFly";
    $website="www.MarcoFly.com";
    $tpl->assign("title",$title);
    $tpl->assign("content",$content);    
    $tpl->assign("auth",$auth);
    $tpl->assign("website",$website);
    $tpl->display("index.dwt");
?>

該index.php就是PHP程式設計師編寫的,可以從資料庫中獲取各種想要的資料,並儲存到變數中,然後簡單的呼叫assign()函式將資料儲存到陣列中,並通過display()函式將編譯檔案輸出

注:此編譯檔案是php檔案,通過伺服器端執行,將結果輸出的客戶端的瀏覽器上

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title><?php echo $this->arr["title"] ?></title>
</head>
<body>
<p>內容:<?php echo $this->arr["content"] ?></p>
<p>作者:<?php echo $this->arr["auth"] ?></p>
<p>網址:<?php echo $this->arr["website"] ?></p>
</body>
</html>

由於我們已經通過assign()函式,將要賦給模板標籤中變數的值儲存到了陣列中了,即此時編譯後的模板檔案,可以直接輸出該陣列中的值了。

舉個例子:

$tpl->assign("title",$title);
當執行了以上兩句程式碼後,在陣列$arr中就存放著下標為:title,值為:深入淺出之Smarty模板引擎工作機制的關聯陣列了。
此時,就可以直接通過$this->arr['title']直接輸出該陣列的值。
至於對如何從<{$title}>  ---> <?php echo $this->arr['title']?> 的轉換,不懂的讀者可以再仔細看下。

有了以上幾個檔案之後,我們在瀏覽器中訪問index.php檔案將得到以下結果:

到此,我們“開發”了一個自己的模板引擎,並且測試成功,當然,這只是供交流學習之用。