将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
<!
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
>
<!--{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
=
'/{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);
//判断是否有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
=
'/{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语句没有关闭'
);
}
}
}
//解析include
private
function
parInclude(){
$_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);
}
}
//解析系统变量
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
评论