此内容用作笔记,以备日后查看,此内容为学习李炎恢课程而来,并非自己所创,如有问题请私信~
将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
转:https://www.cnblogs.com/fkli/p/4810675.html
PHP--关于模板的原理和解析(php模板原理)
原文地址:https://www.cnblogs.com/fps2tao/p/8520258.html