PHP-關於模板的原理和解析

將PHP代碼和靜態HTML代碼進行分離,使代碼的可讀性和維護性得到顯著提高。

使用模板引擎:

    我們所說的模板是Web模板,是主要由HTML標記組成的語言來編寫的頁面,但也有如何表示包含動態生成內容的方式(解析標籤)。模板引擎是一種軟件庫,允許我們從模板生成HTML代碼,並指定要包含的動態內容。

  模板引擎的特點:

  1.鼓勵分離:讓更個系統的可讀性和維護性得到提高。
  2.促進分工:使得程序員和美工去專心處理自己的設計。
  3.比PHP更容易解析:編譯文件和緩存文件加載更快、佔資源更少。
  4.增加安全性:可限制模板設計師進行不安全的操作的能力避免誤刪誤訪問等。

模板處理的流程圖

  \

 

創建模板:

  1、創建初始模板所需要的文件夾和文件。

  a) index.php主文件,用於編寫業務邏輯。
  b) template.inc.php模板初始化文件,用於初始模版信息。
  c) templates目錄存放所有的模板文件。
  d) templates_c目錄存放所有編譯文件。
  e) cache目錄存放所有緩存文件。
  f) includes目錄存放所有的類文件。
  g) config目錄存放模板系統變量配置文件。

  \

  以下是源碼:

主文件 index.php  

複製代碼
php
   //index.php

  //設置編碼爲UTF-8
  header('Content-Type:text/html;Charset=utf-8');
  //網站根目錄
  define('ROOT_PATH', dirname(__FILE__));
  //存放模板文件夾
  define('TPL_DIR', ROOT_PATH.'/templates/');
  //編譯文件夾
  define('TPL_C_DIR', ROOT_PATH.'/templates_c/');
  //緩存文件夾
  define('CACHE_DIR', ROOT_PATH.'/cache/');
  //定義緩存狀態
  define('IS_CACHE',true);
  //設置緩存狀態開關
  IS_CACHE ? ob_start() : null;

  include ROOT_PATH.'/includes/Templates.class.php';

  $_name = '方塊李';
    
    $array = array(1,2,3,4,5,6);
    $_tpl = new Templates();
    $_tpl->assign('name', $_name);
    $_tpl->assign('a', 5>4);
    $_tpl->assign('array', $array);
    //顯示
    $_tpl->display('index.tpl');
?>
複製代碼

模板文件 HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>title>
 
head>
<body>
{include "test.php"}
{#}這是一條PHP的註釋,在HTML頁面裏是不顯示的,只會在生成的編譯文件裏顯示{#}
我將被index.php導入
{$name}這個標籤必須經過Parser.class.php這個解析類來解析它1
<br />
這裏的內容改變了,爲什麼?
<br />
{if $a}
顯示一號皮膚
{else}
顯示二號皮膚
{/if}
<br />
{foreach $array(key,value)}
{@key}....{@value} <br />
{/foreach}
body>
html>

  

模板類:

解析類:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//Parser.class.php
    class Parser {
        //獲取模板內容
        private $_tpl;
        //構造方法,初始化模板
        public function __construct($_tplFile){
            //判斷文件是否存在
            if(!$this->_tpl = file_get_contents($_tplFile)){
                exit('ERROR:讀取模板出錯!');
            }
            
        }
        
        //解析普通變量
        private function parVar(){
            $_pattern '/\{\$([\w]+)\}/';
            if (preg_match($_pattern,$this->_tpl)) {
                $this->_tpl = preg_replace($_pattern,"_vars['$1'] ?>",$this->_tpl);
            }
        }
        //解析IF條件語句
        private function parIf(){
            //開頭if模式
            $_patternIf '/\{if\s+\$([\w]+)\}/';
            //結尾if模式
            $_patternEnd '/\{\/if\}/';
            //else模式
            $_patternElse '/\{else\}/';
            //判斷if是否存在
            if(preg_match($_patternIf$this->_tpl)){
                //判斷是否有if結尾
                if(preg_match($_patternEnd$this->_tpl)){
                    //替換開頭IF
                    $this->_tpl = preg_replace($_patternIf"_vars['$1']){ ?>"$this->_tpl);
                    //替換結尾IF
                    $this->_tpl = preg_replace($_patternEnd""$this->_tpl);
                    //判斷是否有else
                    if(preg_match($_patternElse$this->_tpl)){
                        //替換else
                        $this->_tpl = preg_replace($_patternElse""$this->_tpl);
                    }
                }else{
                    exit('ERROR:語句沒有關閉!');
                }
            }
        }
        //解析foreach
        private function parForeach(){
            $_patternForeach '/\{foreach\s+\$(\w+)\((\w+),(\w+)\)\}/';
            $_patternEndForeach '/\{\/foreach\}/';
            //foreach裏的值
            $_patternVar '/\{@(\w+)\}/';
            //判斷是否存在
            if(preg_match($_patternForeach$this->_tpl)){
                //判斷結束標誌
                if(preg_match($_patternEndForeach$this->_tpl)){
                    //替換開頭
                    $this->_tpl = preg_replace($_patternForeach"_vars['$1'] as \$$2=>\$$3){?>"$this->_tpl);
                    //替換結束
                    $this->_tpl = preg_replace($_patternEndForeach""$this->_tpl);
                    //替換值
                    $this->_tpl = preg_replace($_patternVar""$this->_tpl);
                }else{
                    exit('ERROR:Foreach語句沒有關閉');
                }
            }
        }
        //解析include
        private function parInclude(){
            $_pattern '/\{include\s+\"(.*)\"\}/';
            if(preg_match($_pattern$this->_tpl,$_file)){
                //判斷頭文件是否存在
                if(!file_exists($_file[1]) || empty($_file[1])){
                    exit('ERROR:包含文件不存在!');
                }
                //替換內容
                $this->_tpl = preg_replace($_pattern""$this->_tpl);
            }
        }
        //解析系統變量
        private function configVar(){
            $_pattern '//';
            if(preg_match($_pattern$this->_tpl,$_file)){
                $this->_tpl = preg_replace($_pattern,"_config['$1'] ?>"$this->_tpl);
                
            }
        }
        
        //解析單行PHP註釋
        private function parCommon(){
            $_pattern '/\{#\}(.*)\{#\}/';
            if(preg_match($_pattern$this->_tpl)){
                $this->_tpl = preg_replace($_pattern""$this->_tpl);
            }
        }
        
        
        //生成編譯文件
        public function compile($_parFile){
            //解析模板變量
            $this->parVar();
            //解析IF
            $this->parIf();
            //解析註釋
            $this->parCommon();
            //解析Foreach
            $this->parForeach();
            //解析include
            $this->parInclude();
            //解析系統變量
            $this->configVar();
            //生成編譯文件
            if(!file_put_contents($_parFile$this->_tpl)){
                exit('ERROR:編譯文件生成失敗!');
            }
        }
    }

  

總結:模板引擎的整個過程:

  1、當瀏覽器請求index.php文件時,實例化模板類對像 $_tpl = new Templates();

  2、當Templates實例化的時候,生成兩個數組,一個用來存放模板變量,另一個存放系統變量,通過構造方法,判斷文件夾是否存在,同時通過XML文件將系統變量數組初始化

  3、通過模板類Templates的注入方法,assign(),將對應模板index.tpl中變量的index.php的內容注入到模板類的私有變量,完成初始化

  4、模板類Templates類顯示方法display() 通過實例化解析類Parser,將取到的注入變量通過解析類進行解析(即替換)

  5、解析(替換)後,將文件寫入PHP、HTML混全文件

  6、通過Templates類的顯示方法將文件輸出:

     1、第一次執行顯示方法時,將會把PHP、HTML混合文件,生成純靜態的緩存文件

     2、調用緩存文件,顯示頁面

     3、當瀏覽器再次調用顯示方法時,首先根據各文件的最後修改時間,判斷是否重新生成緩存文件或直接調用已存在的緩存文件

重點:

  1、通過正則表達式進行字符串的替換

  2、熟悉OOP


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章