此内容用作笔记, 以备日后查看, 此内容为学习李炎恢课程而来, 并非自己所创, 如有问题请私信~
将 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;
- }
- }
- }
- 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: 编译文件生成失败 ! );
- }
- }
- }
- View Code
总结: 模板引擎的整个过程:
1 当浏览器请求 index.php 文件时, 实例化模板类对像 $_tpl = new Templates();
2 当 Templates 实例化的时候, 生成两个数组, 一个用来存放模板变量, 另一个存放系统变量, 通过构造方法, 判断文件夹是否存在, 同时通过 XML 文件将系统变量数组初始化
3 通过模板类 Templates 的注入方法, assign(), 将对应模板 index.tpl 中变量的 index.php 的内容注入到模板类的私有变量, 完成初始化
4 模板类 Templates 类显示方法 display() 通过实例化解析类 Parser, 将取到的注入变量通过解析类进行解析(即替换)
5 解析 (替换) 后, 将文件写入 PHPHTML 混全文件
6 通过 Templates 类的显示方法将文件输出:
1 第一次执行显示方法时, 将会把 PHPHTML 混合文件, 生成纯静态的缓存文件
2 调用缓存文件, 显示页面
3 当浏览器再次调用显示方法时, 首先根据各文件的最后修改时间, 判断是否重新生成缓存文件或直接调用已存在的缓存文件
重点:
1 通过正则表达式进行字符串的替换
2 熟悉 OOP
来源: http://www.bubuko.com/infodetail-2518221.html