php制作简单模版引擎


Posted in PHP onApril 07, 2016

PHP模板引擎就是一个PHP类库,使用它可以使PHP代码和HTML代码进行分离,使代码的可读性和维护性得到显著提高。而且这样做的好处是,让美工专心设计HTML前台页面,程序员专心去写PHP业务逻辑。因此,模化引擎很适合公司的Web开发团队使用,使每个人都能发挥其特长

下面我们就来看看如何简单的来实现php的模板引擎

parser.class.php

<?php
 
/**
 * 模版解析类
 */
class Parser
{
  // 字段,接收模版文件内容
  private $_tpl;
   
  // 构造方法,获取模版文件内容
  public function __construct($_tplFile)
  {
    if (! $this->_tpl = file_get_contents($_tplFile)) {
      exit('ERROR:模版文件读取错误');
    }
  }
   
  // 解析普通变量
  private function parvar()
  {
    $_patten = '/<!--\s+\{\$([\w]+)\}\s+-->/';
    if (preg_match($_patten,$this->_tpl)) {
      $this->_tpl = preg_replace($_patten, "<?php echo \$this->_vars['$1'];?>",$this->_tpl);
    }
  }
 
  //解析IF语句
  private function parif(){
    $_pattenif = '/<!--\s+\{if\s+\$([\w]+)\}\s+-->/';
    $_pattenElse = '/<!--\s+\{else\}\s+-->/';
    $_pattenEndif = '/<!--\s+\{\/if\}\s+-->/';
    if (preg_match($_pattenif,$this->_tpl)) {
      if (preg_match($_pattenEndif,$this->_tpl)) {
        $this->_tpl = preg_replace($_pattenif,"<?php if (\$this->_vars['$1']){?>",$this->_tpl);
        $this->_tpl = preg_replace($_pattenEndif,"<?php } ?>",$this->_tpl);
        if (preg_match($_pattenElse,$this->_tpl)) {
          $this->_tpl = preg_replace($_pattenElse,"<?php }else{?>",$this->_tpl);
        }
      }else{
      echo 'ERROR:IF语句没有关闭!';
      }
    }
  }
 
  //PHP注释解析
 
  private function parCommon(){
    $_pattenCommon = '/<!--\s+\{#\}(.*)\{#\}\s+-->/';
    if (preg_match($_pattenCommon,$this->_tpl)) {
      $this->_tpl = preg_replace($_pattenCommon,"<?php /* $1 */ ?>",$this->_tpl);
    }
  }
   
  //解析foreach语句
  private function parForeach(){
    $_pattenForeach = '/<!--\s+\{foreach\s+\$([\w]+)\(([\w]+),([\w]+)\)\}\s+-->/';
    $_pattenForeachEnd = '/<!--\s+\{\/foreach\}\s+-->/';
    $_pattenForeachValue = '/<!--\s+\{@([\w]+)\}\s+-->/';
    if (preg_match($_pattenForeach,$this->_tpl)) {
      if (preg_match($_pattenForeachEnd,$this->_tpl)) {
        $this->_tpl = preg_replace($_pattenForeach, "<?php foreach (\$this->_vars['$1'] as \$$2=>\$$3) {?>", $this->_tpl);
        $this->_tpl = preg_replace($_pattenForeachEnd, "<?php }?>", $this->_tpl);
        if (preg_match($_pattenForeachValue, $this->_tpl)) {
          $this->_tpl = preg_replace($_pattenForeachValue,"<?php echo \$$1;?>",$this->_tpl);
        }
      }else{
      echo 'ERROR:Foreach语句没有关闭!';  
      }
    }
  }
 
  //解析include方法
  private function parInclude(){
    $_pattenInclude = '/<!--\s+\{include\s+file=\"([\w\.\-]+)\"\}\s+-->/';
    if (preg_match($_pattenInclude,$this->_tpl,$_file,$_file)) {
      if (!file_exists($_file[1])||empty($_file)) {
        echo 'ERROR:包含文件出错!';
      }
      $this->_tpl = preg_replace($_pattenInclude,"<?php include '$1';?>",$this->_tpl);
    }
  }
 
  //解析系统变量方法
  private function parConfig(){
    $_pattenConfig = '/<!--\s+\{([\w]+)\}\s+-->/';
    if (preg_match($_pattenConfig,$this->_tpl)) {
      $this->_tpl = preg_replace($_pattenConfig,"<?php echo \$this->_config['$1'];?>",$this->_tpl);
    }
  }
  // 对外公共方法
  public function compile($_path)
  {
    // 解析模版文件
    $this->parvar();
    $this->parif();
    $this->parForeach();
    $this->parInclude();
    $this->parCommon();
    $this->parConfig();
    // 生成编译文件
    if (! file_put_contents($_path, $this->_tpl)) {
      exit('ERROR:编译文件生成错误!');
    }
  }
}
?>

Templates.class.php

<?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) || !is_dir(CONFIG)) {
      echo 'ERROR:模版目录或编译目录,缓存目录不存在!自动创建!'."<br />";
      if (!is_dir(TPL_DIR)) {
        mkdir(TPL_DIR);
        echo '模版目录'.TPL_DIR.'建立'."<br />";
      }
      if (!is_dir(TPL_C_DIR)) {
        mkdir(TPL_C_DIR);
        echo '编译目录'.TPL_C_DIR.'建立'."<br />";
      }
      if (!is_dir(CACHE)) {
        mkdir(CACHE);
        echo '缓存目录'.CACHE.'建立'."<br />";
      }
      if (!is_dir(CONFIG)) {
        mkdir(CONFIG);
        echo '缓存目录'.CONFIG.'建立'."<br />";
      }
      exit();
    }
    //保存系统变量
    $_sxe = simplexml_load_file(CONFIG.'/config.xml');
    $_tagLib = $_sxe->xpath('/root/taglib');
    foreach ($_tagLib as $_tag) {
      $this->_config["$_tag->name"] = $_tag->value;
    }
  }
 
  //assign()方法,用于注入变量
  public function assign($_var,$_value){
    //$_var用于同步模版里的变量名
    //$_value表示值
    if (isset($_var)&&!empty($_var)) {
      $this->_vars[$_var] = $_value;
    }else{
      exit('ERROR:设置模版变量!');
    }
 
  }
 
  //display()方法
  public function display($_file)
  {
    $_tplFile = TPL_DIR . $_file;
    // 判断文件是否存在
    if (! file_exists($_tplFile)) {
      echo 'ERROR:模版文件不存在!自动创建Index.tpl模版文件!';
      file_put_contents($_tplFile,'Index');
      exit();
    }
 
    //生成编译文件
    $_path = TPL_C_DIR.md5($_file).'-'.$_file.'.php';
    //缓存文件
    $_cacheFile = CACHE.md5($_file).'-'.$_file.'.html';
    //当第二次运行相同文件,直接载入缓存文件
    if (IS_CACHE) {
      //判断缓存文件和编译文件都存在
      if (file_exists($_cacheFile)&&file_exists($_path)) {
        //判断模版文件是否修改过
        if (filemtime($_path)>=filemtime($_tplFile)&&filemtime($_cacheFile)>=filemtime($_path)) {
          include $_cacheFile;
          echo '<!--cache-->';
          return;
        }
      }
    }
    //当编译文件不存在或者文件发生改变则重新生成
    if (!file_exists($_path)||filemtime($_path)<filemtime($_tplFile)) {
      require ROOT_PATH.'/Class/parser.class.php';
      //构造方法是传入模版文件地址
      $_parser = new Parser($_tplFile);
      //传入编译文件地址
      $_parser->compile($_path);
    }
    //载入编译文件
    include $_path;
    if (IS_CACHE) {
      //获取缓冲区数据
      file_put_contents($_cacheFile,ob_get_contents());
      //清楚缓冲区
      ob_end_clean();
      //载入缓存文件
      include $_cacheFile;
    }
  }
}
?>

templates.php

<?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',ROOT_PATH.'/Cache/');
 
//系统变量配置目录
define('CONFIG',ROOT_PATH.'/Config/');
 
//是否开启缓冲区
define('IS_CACHE',false);//false
 
//判断是否需要开启
IS_CACHE ? ob_start() : null;
 
//引入模版类
require ROOT_PATH.'/Class/Templates.class.php';
 
//实例化模版类
$_tpl=new Templates();
 
$_tpl->display('index.tpl');
?>

templates/index.tpl

<!DOCTYPE html>
<html lang="zn-cn">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  <meta name="description" content="">
  <meta name="keywords" content="">
  <meta name="author" content="">
  <meta name="author" content="">
  <title><!-- {WebName} --></title>
  <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
  <link rel="stylesheet" type="text/css" href="css/style.css">
  </head>
<body>
 
<!-- {#}php注释{#} -->
<!-- {if $a} -->
123
<!-- {else} -->
321
<!-- {/if} -->
<br />
<!-- {foreach $array(key,value)} -->
  <!-- {@key} -->...<!-- {@value} --><br />
<!-- {/foreach} -->
系统变量<!-- {WebName} --><br />
普通变量<!-- {$name} --><br />

  <script src="/js/jquery-2.2.1.min.js" type="text/javascript"></script>
  <script src="/js/bootstrap.min.js" type="text/javascript"></script>
  <script type="text/javascript">
  </script>
</body>
</html>

config/config.xml

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <taglib>
    <name>WebName</name>
    <value>XXX网站</value>
  </taglib>
</root>
PHP 相关文章推荐
mysql总结之explain
Feb 27 PHP
php数组中包含中文的排序方法
Jun 03 PHP
ThinkPHP之N方法实例详解
Jun 20 PHP
Yii框架form表单用法实例
Dec 04 PHP
PHP5全版本绕过open_basedir读文件脚本漏洞详细介绍
Jan 20 PHP
php使用curl出现Expect:100-continue解决方法
Mar 03 PHP
PHP 绘制网站登录首页图片验证码
Apr 12 PHP
php简单统计在线人数的方法
May 10 PHP
Ubuntu VPS中wordpress网站打开时提示”建立数据库连接错误”的解决办法
Nov 03 PHP
Laravel如何使用数据库事务及捕获事务失败后的异常详解
Oct 23 PHP
PHP获取对象属性的三种方法实例分析
Jan 03 PHP
php无限极分类实现方法分析
Jul 04 PHP
thinkphp框架下实现登录、注册、找回密码功能
Apr 06 #PHP
非常有用的9个PHP代码片段
Apr 06 #PHP
10个对初学者非常有用的PHP技巧
Apr 06 #PHP
yii2.0实现pathinfo的形式访问的配置方法
Apr 06 #PHP
PHP实现的DES加密解密实例代码
Apr 06 #PHP
php使用正则验证中文
Apr 06 #PHP
php HTML无刷新提交表单
Apr 05 #PHP
You might like
php中file_get_content 和curl以及fopen 效率分析
2014/09/19 PHP
浅谈本地WAMP环境的搭建
2015/05/13 PHP
php判断表是否存在的方法
2015/06/18 PHP
PHP实现的redis主从数据库状态检测功能示例
2017/07/20 PHP
php实现等比例压缩图片
2018/07/26 PHP
Thinkphp 框架基础之源码获取、环境要求与目录结构分析
2020/04/27 PHP
基于jQuery的history历史记录插件
2010/12/11 Javascript
在js文件中写el表达式取不到值的原因及解决方法
2013/12/23 Javascript
二叉树的非递归后序遍历算法实例详解
2014/02/07 Javascript
js创建表单元素并使用submit进行提交
2014/08/14 Javascript
node.js中的fs.close方法使用说明
2014/12/17 Javascript
javascript手工制作悬浮菜单
2015/02/12 Javascript
jQuery+html5+css3实现圆角无刷新表单带输入验证功能代码
2015/08/21 Javascript
jquery mobile开发常见问题分析
2016/01/21 Javascript
浅谈json取值(对象和数组)
2016/06/24 Javascript
Extjs 点击复选框在表格中增加相关信息行
2016/07/12 Javascript
JavaScript操作文件_动力节点Java学院整理
2017/06/30 Javascript
jQuery实现每隔一段时间自动更换样式的方法分析
2018/05/03 jQuery
redux.js详解及基本使用
2019/05/24 Javascript
JavaScript模块管理的简单实现方式详解
2019/06/15 Javascript
微信小程序实现语音识别转文字功能及遇到的坑
2019/08/02 Javascript
利用Pyhton中的requests包进行网页访问测试的方法
2018/12/26 Python
pytorch的梯度计算以及backward方法详解
2020/01/10 Python
python 将dicom图片转换成jpg图片的实例
2020/01/13 Python
探秘TensorFlow 和 NumPy 的 Broadcasting 机制
2020/03/13 Python
python中如何进行连乘计算
2020/05/28 Python
教导处工作制度
2014/01/18 职场文书
宣传口号大全
2014/06/16 职场文书
护理目标管理责任书
2014/07/25 职场文书
少先队活动总结
2014/08/29 职场文书
2014年9.18纪念日演讲稿
2014/09/14 职场文书
早读课迟到检讨书
2014/09/25 职场文书
500字小学生检讨书
2015/02/19 职场文书
初中生思想道德自我评价
2015/03/09 职场文书
幼儿园教师岗位职责
2015/04/02 职场文书
创业计划书详解
2019/07/19 职场文书