将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目录存放模板系统变量配置文件。

以下是源码:
主要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
<!DOCTYPEhtml PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><head><metahttp-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:classTemplates {//创建一个存放数组的字段private$_vars=array();private$_config=array();//创建一个构造方法publicfunction__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($_taglibas$_tag){$this->_config["$_tag->name"] =$_tag->value;}}//创建变量注入方法/*** assign()变量注入方法* @param $_var 要注入的变量名,对应.tpl文件中的需要替换的变量* @param $_values 要注入的变量值*/publicfunctionassign($_var,$_values){if(isset($_var) && !empty($_var)){$this->_vars[$_var] =$_values;}else{exit('ERROR:请设置变量名!');}}//创建一个显示方法,用来显示编译后的文件publicfunctiondisplay($_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))){//引入模板解析类requireROOT_PATH.'/includes/Parser.class.php';//实例化对象,生成编译文件$_parser=newParser($_tplFile);//模板文件$_parser->compile($_parFile);//编译后文件}//载入编译文件include$_parFile;if(IS_CACHE){//生成缓存文件file_put_contents($_cacheFile, ob_get_contents());//清除缓冲区ob_end_clean();//载入缓存文件include$_cacheFile;}}}
//Parser.class.phpclassParser {//获取模板内容private$_tpl;//构造方法,初始化模板publicfunction__construct($_tplFile){//判断文件是否存在if(!$this->_tpl =file_get_contents($_tplFile)){exit('ERROR:读取模板出错!');}}//解析普通变量privatefunctionparVar(){$_pattern='/{$([w]+)}/';if(preg_match($_pattern,$this->_tpl)) {$this->_tpl = preg_replace($_pattern,"<?php echo $this->_vars['$1'] ?>",$this->_tpl);}}//解析IF条件语句privatefunctionparIf(){//开头if模式$_patternIf='/{ifs+$([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);//判断是否有elseif(preg_match($_patternElse,$this->_tpl)){//替换else$this->_tpl = preg_replace($_patternElse,"<?php }else{ ?>",$this->_tpl);}}else{exit('ERROR:语句没有关闭!');}}}//解析foreachprivatefunctionparForeach(){$_patternForeach='/{foreachs+$(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语句没有关闭');}}}//解析includeprivatefunctionparInclude(){$_pattern='/{includes+"(.*)"}/';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);}}//解析系统变量privatefunctionconfigVar(){$_pattern='/<!--{(w+)}-->/';if(preg_match($_pattern,$this->_tpl,$_file)){$this->_tpl = preg_replace($_pattern,"<?php echo $this->_config['$1'] ?>",$this->_tpl);}}//解析单行PHP注释privatefunctionparCommon(){$_pattern='/{#}(.*){#}/';if(preg_match($_pattern,$this->_tpl)){$this->_tpl = preg_replace($_pattern,"<?php /*($1) */?>",$this->_tpl);}}//生成编译文件publicfunctioncompile($_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


评论