此內容用作筆記,以備日後查看,此內容為學習李炎恢課程而來,並非自己所創,如有問題請私信~
將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
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title><!--{webname}--></title> </head> <body> {include "test.php"} <!-- 這是HTML的注釋 --> {#}這是一條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>
模板類:
//Templates.class.php class Templates { //創建一個存放數組的字段 private $_vars = array(); private $_config = array(); //創建一個構造方法 public function __construct(){ if(!is_dir(TPL_DIR) || !is_dir(TPL_C_DIR) || !is_dir(CACHE_DIR) ){ exit('ERROR:模板文件夾或者編譯文件夾或者緩存文件夾沒有創建!'); } //獲取系統變量 $_sxe = simplexml_load_file(ROOT_PATH.'/config/profile.xml'); $_taglib = $_sxe->xpath('/root/taglib'); foreach($_taglib as $_tag){ $this->_config["$_tag->name"] = $_tag->value; } } //創建變量注入方法 /** * assign()變量注入方法 * @param $_var 要注入的變量名,對應.tpl文件中的需要替換的變量 * @param $_values 要注入的變量值 */ public function assign($_var,$_values){ if(isset($_var) && !empty($_var)){ $this->_vars[$_var] = $_values; }else{ exit('ERROR:請設置變量名!'); } } //創建一個顯示方法,用來顯示編譯後的文件 public function display($_file){ //設置模板文件的路徑 $_tplFile = TPL_DIR.$_file; //判斷模板文件是否存在 if(!file_exists($_tplFile)){ exit('ERROR:模板文件不存在'); } //設置編譯文件名 $_parFile = TPL_C_DIR.md5($_file).$_file.'.php'; //設置緩存文件名 $_cacheFile = CACHE_DIR.md5($_file).$_file.'.html'; //判斷緩存狀態 if(IS_CACHE){ //判斷緩存文件是否存在 if(file_exists($_cacheFile) && file_exists($_parFile)){ //是否修改過編譯文件或者模板文件 if(filemtime($_cacheFile)>=filemtime($_parFile) && filemtime($_parFile)>filemtime($_tplFile)){ echo '以下是緩存文件內容'; echo "<br />"; include $_cacheFile; return; } } } //判斷編譯文件是否存在,模板文件是否修改過 if(!file_exists($_parFile) || (filemtime($_parFile) < filemtime($_tplFile))){ //引入模板解析類 require ROOT_PATH.'/includes/Parser.class.php'; //實例化對象,生成編譯文件 $_parser = new Parser($_tplFile);//模板文件 $_parser->compile($_parFile);//編譯後文件 } //載入編譯文件 include $_parFile; if(IS_CACHE){ //生成緩存文件 file_put_contents($_cacheFile, ob_get_contents()); //清除緩沖區 ob_end_clean(); //載入緩存文件 include $_cacheFile; } } }
解析類:
//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,"<?php echo \$this->_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, "<?php if(\$this->_vars['$1']){ ?>", $this->_tpl); //替換結尾IF $this->_tpl = preg_replace($_patternEnd, "<?php } ?>", $this->_tpl); //判斷是否有else if(preg_match($_patternElse, $this->_tpl)){ //替換else $this->_tpl = preg_replace($_patternElse, "<?php }else{ ?>", $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, "<?php foreach(\$this->_vars['$1'] as \$$2=>\$$3){?>", $this->_tpl); //替換結束 $this->_tpl = preg_replace($_patternEndForeach, "<?php } ?>", $this->_tpl); //替換值 $this->_tpl = preg_replace($_patternVar, "<?php echo \$$1?>", $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, "<?php include '$1';?>", $this->_tpl); } } //解析系統變量 private function configVar(){ $_pattern = '/<!--\{(\w+)\}-->/'; if(preg_match($_pattern, $this->_tpl,$_file)){ $this->_tpl = preg_replace($_pattern,"<?php echo \$this->_config['$1'] ?>", $this->_tpl); } } //解析單行PHP注釋 private function parCommon(){ $_pattern = '/\{#\}(.*)\{#\}/'; if(preg_match($_pattern, $this->_tpl)){ $this->_tpl = preg_replace($_pattern, "<?php /*($1) */?>", $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