您的位置:首页 > 其它

关于模板的原理和解析

2015-10-06 02:53 591 查看
将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导入
{$nam
ddc3
e}这个标签必须经过Parser.class.php这个解析类来解析它1
<br />
这里的内容改变了,为什么?
<br />
{if $a}
显示一号皮肤
{else}
显示二号皮肤
{/if}
<br />
{foreach $array(key,value)}
{@key}....{@value} <br />
{/foreach}
</body>
</html>

  

模板类:
+ View Code

解析类:

//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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: