PHP模版引擎原理、定义与用法实例


Posted in PHP onMarch 29, 2019

本文实例讲述了PHP模版引擎原理、定义与用法。分享给大家供大家参考,具体如下:

template存放模版源文件

模版编译工具类

Compline.class.php

<?php
/**
* 模板编译工具类
*/
class Compile
{
  private $template;     //带编译文件
  private $content;      //需要替换的文本
  private $comfile;      //编译后的文件
  private $left = '{';     //左界定符
  private $right = '}';    //右界定符
  private $value = array();   //值栈
  private $php_turn;
  private $T_P = array();
  private $T_R = array();
  public function __construct($template, $compileFile, $config)
  {
   $this->template = $template;
   $this->comfile = $compileFile;
   $this->content = file_get_contents($template);
   if($config['php_turn'] === false)
   {
     $this->T_P[] = "/<\?(=|php|)(.+?)\?>/is";
     $this->T_R[] = "<? \\1\\2? >";
   }
   //{$var}
   $this->T_P[] = "/\{\\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}/";
   //{foreach $b}或者{loop $b}
   $this->T_P[] = "/\{(loop|foreach) \\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}/i";
   //{[K|V]}
   $this->T_P[] = "/\{([K|V])\}/";
   //{/foreach}或者{\loop}或者{\if}
   $this->T_P[] = "/\{\/(loop|foreach|if)}/i";
   //{if (condition)}
   $this->T_P[] = "/\{if (.* ?)\}/i";
   //{(else if | elseif)}
   $this->T_P[] = "/\{(else if|elseif) (.* ?)\}/i";
   //{else}
   $this->T_P[] = "/\{else\}/i";
   //{#...# 或者 *...#,注释}
   $this->T_P[] = "/\{(\#|\*)(.* ?)(\#|\*)\}/";
   $this->T_R[] = "<?php echo \$this->value['\\1']; ?>";
   $this->T_R[] = "<?php foreach ((array)\$this->value['\\2'] as \$K => \$V) { ?>";
   $this->T_R[] = "<?php echo \$\\1; ?>";
   $this->T_R[] = "<?php } ?>";
   $this->T_R[] = "<?php if (\\1) { ?>";
   $this->T_R[] = "<?php }else if (\\2) { ?>";
   $this->T_R[] = "<?php }else{ ?>";
   $this->T_R[] = "";
  }
  public function compile()
  {
   $this->c_all();
   $this->c_staticFile();
   file_put_contents($this->comfile, $this->content);
  }
  public function c_all()
  {
   $this->content = preg_replace($this->T_P, $this->T_R, $this->content);
  }
  /**
  * 加入对JavaScript文件的解析
  * @return [type] [description]
  */
  public function c_staticFile()
  {
   $this->content = preg_replace('/\{\!(.* ?)\!\}/', '<script src=\\1'.'?t='.time().'></script>', $this->content);
  }
  public function __set($name, $value)
  {
   $this->$name = $value;
  }
  public function __get($name)
  {
   if(isset($this->$name))
   {
     return $this->$name;
   }
   else
   {
     return null;
   }
  }
}

Template.class.php

<?php
/**
* Template
*/
class Template
{
  private $arrayConfig = array(
   'suffix'   => '.tpl',  //模板的后缀
   'templateDir' => 'template/', //模板所在的文件夹
   'compileDir'  => 'cache/',  //编译后存放的目录
   'cache_html'  => true,   //是否需要编译成静态的html文件
   'suffix_cache' => '.html',  //设置编译文件的后缀
   'cache_time'  => 7200,   //设置多长时间自动更新
   'php_turn'  => true,   //设置是否支持php原生代码
   'debug'     => false,
   );
  public $file;         //模板文件名,不带路径
  public $debug = array();     //调试信息
  private $value = array();    //值栈
  private $compileTool;      //编译器
  private $controlData = array();
  static private $instance = null;  //模板类对象
  public function __construct($arrayConfig = array())
  {
   $this->debug['begin'] = microtime(true);
   $this->arrayConfig = array_merge($this->arrayConfig, $arrayConfig);
   $this->getPath();
   if(!is_dir($this->arrayConfig['templateDir']))
   {
     exit("template dir isn't found!");
   }
   if(!is_dir($this->arrayConfig['compileDir']))
   {
     if(strtoupper(substr(PHP_OS,0,3)) === 'WIN')
     {
      mkdir($this->arrayConfig['compileDir']);
     }
     else
     {
      mkdir($this->arrayConfig['compileDir'], 0770, true);
     }
   }
   include('Compile.class.php');
  }
  public function getPath()
  {
   $this->arrayConfig['templateDir'] = strstr(realpath($this->arrayConfig['templateDir']), '\\', '/').'/';
   $this->arrayConfig['compileDir'] = strstr(realpath($this->arrayConfig['compileDir'])), '\\', '/').'/';
  }
  /**
  * 取得模板引擎的实例
  */
  public static function getInstance()
  {
   if(is_null(self::$instance))
   {
     self::$instance = new Template();
   }
   return self::$instance;
  }
  /**
  * 单独设置引擎参数
  * 也支持一次性设置多个参数
  */
  public function setConfig($key, $value = null)
  {
   if(is_array($key))
   {
     $this->arrayConfig = $key + $this->arrayConfig;
   }
   else
   {
     $this->arrayConfig[$key] = $value;
   }
  }
  /**
  * 获取当前模板引擎配置,仅供调试使用
  */
  public function getConfig($key = null)
  {
   if($key && array_key_exists($key, $this->arrayConfig))
   {
     return $this->arrayConfig[$key];
   }
   else
   {
     return $this->arrayConfig;
   }
  }
  /**
  * 注入单个变量
  */
  public function assign($key, $value)
  {
   $this->value[$key] = $value;
  }
  /**
  * 注入数组变量
  */
  public function assignArray($array)
  {
   if(is_array($array))
   {
     foreach ($array as $k => $v) {
      $this->value[$k] = $v;
     }
   }
  }
  /**
  * 获取模板的位置
  * @return [type] [description]
  */
  public function path()
  {
   return $this->arrayConfig['templateDir'].$this->file.$this->arrayConfig['suffix'];
  }
  /**
  * 判断配置文件是否要求缓存
  */
  public function needCache()
  {
   return $this->arrayConfig['cache_html'];
  }
  /**
  * 判断是否需要缓存
  */
  public function reCache($file)
  {
   $flag = false;
   $cacheFile = $this->arrayConfig['compileDir'].md5($file).$this->arrayConfig['suffix_cache'];
   if($this->arrayConfig['cache_html'] === true)
   {
     //需要缓存
     $timeFlag = (time() - @filemtime($cacheFile)) < $this->arrayConfig['cache_time'] ? true : false;
     if(is_file($cacheFile) && filesize($cacheFile) > 1 && $timeFlag)
     {
      //缓存存在且未过期
      $flag = true;
     }
     else
     {
      $flag = false;
     }
   }
   return $flag;
  }
  /**
  * 展示模板
  */
  public function show($file)
  {
   $this->file = $file;
   if(!is_file($this->path()))
   {
     exit('找不到对应的模板');
   }
   $compileFile = $this->arrayConfig['compileDir'].md5($file).'.php';
   $cacheFile = $this->arrayConfig['compileDir'].md5($file).$this->arrayConfig['suffix_cache'];
   if($this->reCache($file) === false)
   {
     //如果需要缓存
     $this->debug['cached'] = 'false';
     $this->compileTool = new Compile($this->path(), $compileFile, $this->arrayConfig);
     if($this->needCache())
     {
      ob_start();
     }
     extract($this->value, EXTR_OVERWRITE);
     if(!is_file($compileFile) || fileatime($compileFile) < filemtime($this->path()))
     {
      $this->compileTool->value = $this->value;
      $this->compileTool->compile();
      include $compileFile;
     }
     else
     {
      include $compileFile;
     }
     if($this->needCache())
     {
      $message = ob_get_contents();
      file_put_contents($cacheFile, $message);
     }
   }
   else
   {
     readfile($cacheFile);
     $this->debug['cached'] = 'true';
   }
   $this->debug['spend'] = microtime(true) - $this->debug['begin'];
   $this->debug['count'] = count($this->value);
   $this->debug_info();
  }
  public function debug_info()
  {
   if($this->arrayConfig['debug'] === true)
   {
     echo "<br/>", '-------------------- debug_info--------------', "<br/>";
     echo '程序运行日期:', date("Y-m-d h:i:s"), "<br/>";
     echo '模板解析耗时:', $this->debug['spend'], '秒', "<br/>";
     echo '模板包含标签数目:', $this->debug['count'], "<br/>";
     echo '是否使用静态缓存:', $this->debug['cached'], "<br/>";
     echo '模板引擎实例参数:', var_dump($this->getConfig());
   }
  }
  /**
  * 清楚缓存的html文件
  * @return [type] [description]
  */
  public function clean()
  {
   if($path === null)
   {
     $path = $this->arrayConfig['compileDir'];
     $path = glob($path.'* '.$this->arrayConfig['suffix_cache']);
   }
   else
   {
     $path = $this->arrayConfig['compileDir'].md5($path).$this->arrayConfig['suffix_cache'];
   }
   foreach ((array)$path as $v) {
     unlink($v);
   }
  }
}

test.php

<?php
include 'Template.class.php';
$tpl = new Template(array('debug' => true));
$tpl->assign('data', 'hello world');
$tpl->assign('person', 'htGod');
$tpl->assign('data1', 3);
$arr = array(1,2,3,4,'5',6);
$tpl->assign('b', $arr);
$tpl->show('member');

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
使用sockets:从新闻组中获取文章(二)
Oct 09 PHP
实用函数2
Nov 08 PHP
解析php中curl_multi的应用
Jul 17 PHP
PHP 登录完成后如何跳转上一访问页面
Jan 14 PHP
PHP中redis的用法深入解析
Feb 20 PHP
php模拟登陆的实现方法分析
Jan 09 PHP
php字符串函数学习之strstr()
Mar 27 PHP
PHP实现即时输出、实时输出内容方法
May 27 PHP
Thinkphp关闭缓存的方法
Jun 26 PHP
php基于双向循环队列实现历史记录的前进后退等功能
Aug 08 PHP
php 利用array_slice函数获取随机数组或前几条数据
Sep 30 PHP
[原创]PHP获取数组表示的路径方法分析【数组转字符串】
Sep 01 PHP
为Plesk PHP7启用Oracle OCI8扩展方法总结
Mar 29 #PHP
PHP中ltrim()函数的用法与实例讲解
Mar 28 #PHP
CodeIgniter框架实现的整合Smarty引擎DEMO示例
Mar 28 #PHP
PHP微商城开源代码实例
Mar 27 #PHP
PHP简单验证码功能机制实例详解
Mar 27 #PHP
PHP判断访客是否手机端(移动端浏览器)访问的方法总结【4种方法】
Mar 27 #PHP
PHP实现数据四舍五入的方法小结【4种方法】
Mar 27 #PHP
You might like
星际争霸教主Flash的ID由来:你永远不会知道他之前的ID是www!
2019/01/18 星际争霸
理解PHP5中static和const关键字的区别
2007/03/19 PHP
php中利用str_pad函数生成数字递增形式的产品编号
2013/09/30 PHP
php实现的二叉树遍历算法示例
2017/06/15 PHP
PHP实现超简单的SSL加密解密、验证及签名的方法示例
2017/08/28 PHP
js 蒙版进度条(结合图片)
2010/03/10 Javascript
JavaScript 异步方法队列链实现代码分析
2010/06/05 Javascript
一个可拖拽列宽表格实例演示
2012/11/26 Javascript
jquery做的一个简单的屏幕锁定提示框
2014/03/26 Javascript
jQuery中ajax的load()方法用法实例
2014/12/26 Javascript
使用console进行性能测试
2015/04/27 Javascript
js 数据存储和DOM编程
2017/02/09 Javascript
百度地图JavascriptApi Marker平滑移动及车头指向行径方向
2017/03/13 Javascript
基于Cookie常用操作以及属性介绍
2017/09/07 Javascript
在vue中,v-for的索引index在html中的使用方法
2018/03/06 Javascript
解决vue+webpack打包路径的问题
2018/03/06 Javascript
详解element-ui中表单验证的三种方式
2019/09/18 Javascript
JavaScript冒泡算法原理与实现方法深入理解
2020/06/04 Javascript
python3序列化与反序列化用法实例
2015/05/26 Python
python列出目录下指定文件与子目录的方法
2015/07/03 Python
关于Python元祖,列表,字典,集合的比较
2017/01/06 Python
python调用API实现智能回复机器人
2018/04/10 Python
pandas 转换成行列表进行读取与Nan处理的方法
2018/10/30 Python
Python字典的核心底层原理讲解
2019/01/24 Python
Python2.7:使用Pyhook模块监听鼠标键盘事件-获取坐标实例
2020/03/14 Python
python中return如何写
2020/06/18 Python
美国杂志订阅折扣与优惠网站:Magazines.com
2016/08/31 全球购物
King Apparel官网:英国街头服饰品牌
2019/09/05 全球购物
Stokke美国官方网店:高级儿童家具、推车、汽车座椅和配件
2020/06/06 全球购物
纯净、自信、100%的羊绒服装:360Cashmere
2021/02/20 全球购物
优秀的茶餐厅创业计划书
2014/01/03 职场文书
社区党员先进事迹
2014/01/22 职场文书
安全标准化汇报材料
2014/02/03 职场文书
应聘编辑自荐信范文
2014/03/12 职场文书
社区文艺活动方案
2014/08/19 职场文书
Java使用jmeter进行压力测试
2021/07/09 Java/Android