摘要:本文实例讲述了PHP模板解析类。分享给大家供大家参考。具体如下:<?php

class template {

private $vars = array();

private $conf = '';

private $tpl_name =&n

本文实例讲述了PHP模板解析类。分享给大家供大家参考。具体如下:<?php

class template {

private $vars = array();

private $conf = '';

private $tpl_name = 'index';

//如果模板不存在 会查找当前 controller默认index模板

private $tpl_suffix = '.html';//如果CONFIG没配置默认后缀 则显示

private $tpl_compile_suffix= '.tpl.php';//编译模板路径

private $template_tag_left = '

private $template_tag_right = '}>';//模板右标签

private $template_c = '';//编译目录

private $template_path = '';//模板完整路径

private $template_name = '';//模板名称 index.html

//定义每个模板的标签的元素

private $tag_foreach = array('from', 'item', 'key');

private $tag_include = array('file');//目前只支持读取模板默认路径

public function __construct($conf) {

$this->conf = &$conf;

$this->template_c = $this->conf['template_config']['template_c'];//编译目录

$this->_tpl_suffix = $this->tpl_suffix();

}

private function str_replace($search, $replace, $content) {

if(empty($search) || empty($replace) || empty($content)) return false;

return str_replace($search, $replace, $content);

}

/**

* preg_match_all

* @param $pattern 正则

* @param $content 内容

* @return array

*/

private function preg_match_all($pattern, $content) {

if(empty($pattern) || empty($content)) core::show_error('查找模板标签失败!');

preg_match_all("/".$this->template_tag_left.$pattern.$this->template_tag_right."/is", $content, $match);

return $match;

}

/**

* 模板文件后缀

*/

public function tpl_suffix() {

$tpl_suffix = empty($this->conf['template_config']['template_suffix']) ?

$this->tpl_suffix :

$this->conf['template_config']['template_suffix'] ;

return $tpl_suffix;

}

/**

* 此处不解释了

* @return

*/

public function assign($key, $value) {

$this->vars[$key] = $value;

}

/**

* 渲染页面

* @param

* 使用方法 1

* $this->view->display('error', 'comm/');

* 默认是指向TPL模版的跟目录,所以comm/就是 tpl/comm/error.html

* 使用方法 2

* $this->view->display('errorfile');

* 默认指向控制器固定的文件夹

* 例如你的域名是 http://heartphp/admin/index, 那么正确路径就是tpl/admin/index/errorfile.html

* @return

*/

public function display($filename = '', $view_path = '') {

$tpl_path_arr = $this->get_tpl($filename, $view_path);//获取TPL完整路径 并且向指针传送路径以及名称

if(!$tpl_path_arr) core::show_error($filename.$this->_tpl_suffix.'模板不存在');

//编译开始

$this->view_path_param = $view_path;//用户传递过来的模版跟目录

$this->compile();

}

/**

* 编译控制器

* @param

* @return

*/

private function compile() {

$filepath = $this->template_path.$this->template_name;

$compile_dirpath = $this->check_temp_compile();

$vars_template_c_name = str_replace($this->_tpl_suffix, '', $this->template_name);

$include_file = $this->template_replace($this->read_file($filepath), $compile_dirpath, $vars_template_c_name);//解析

if($include_file) {

$this->read_config() && $config = $this->read_config();

extract($this->vars, EXTR_SKIP);

[url=home.php?mod=space&uid=48608]@include[/url] $include_file;

}

}

/**

* 读取当前项目配置文件

*/

protected function read_config() {

if(file_exists(SYSTEM_PATH.'conf/config.php')) {

@include SYSTEM_PATH.'conf/config.php';

return $config;

}

return false;

}

/**

* 解析模板语法

* @param $str 内容

* @param $compile_dirpath 模版编译目录

* @param $vars_template_c_name 模版编译文件名

* @return 编译过的PHP模板文件名

*/

private function template_replace($str, $compile_dirpath, $vars_template_c_name) {

if(empty($str)) core::show_error('模板内容为空!');

//处理编译头部

$compile_path = $compile_dirpath.$vars_template_c_name.$this->tpl_compile_suffix;//编译文件

if(is_file($compile_path)) {

//$header_content = $this->get_compile_header($compile_path);

//$compile_date = $this->get_compile_header_comment($header_content);

$tpl_filemtime = filemtime($this->template_path.$this->template_name);

$compile_filemtime = filemtime($compile_path);

//echo $tpl_filemtime.'=='.date('Y-m-d H:i:s', $tpl_filemtime).'
';

//echo $compile_filemtime.'=='.date('Y-m-d H:i:s', $compile_filemtime);

//如果文件过期编译 当模板标签有include并且有修改时 也重新编译

// 当修改include里的文件,非DEBUG模式时 如果不更改主文件 目前是不重新编译include里的文件,我在考虑是否也要更改,没想好,暂时这样,所以在开发阶段一定要开启DEBUG=1模式 要不然修改include文件无效 。 有点罗嗦,不知道表述清楚没

if($tpl_filemtime > $compile_filemtime || DEBUG) {

$ret_file = $this->compile_file($vars_template_c_name, $str, $compile_dirpath);

} else {

$ret_file = $compile_path;

}

} else {//编译文件不存在 创建他

$ret_file = $this->compile_file($vars_template_c_name, $str, $compile_dirpath);

}

return $ret_file;

}

/**

* 模板文件主体

* @param string $str 内容

* @return html

*/

private function body_content($str) {

//解析

$str = $this->parse($str);

$header_comment = "Create On##".time()."|Compiled from##".$this->template_path.$this->template_name;

$content = " if(!defined('IS_HEARTPHP')) exit('Access Denied');/*{$header_comment}*/?>\r\n$str";

return $content;

}

/**

* 开始解析相关模板标签

* @param $content 模板内容

*/

private function parse($content) {

//foreach

$content = $this->parse_foreach($content);

//include

$content = $this->parse_include($content);

//if

$content = $this->parse_if($content);

//elseif

$content = $this->parse_elseif($content);

//模板标签公用部分

$content = $this->parse_comm($content);

//转为PHP代码

$content = $this->parse_php($content);

return $content;

}

/**

* echo 如果默认直接 转成 <?php  echo $config['domain']?>

*/

private function parse_echo($content) {

}

/**

* 转换为PHP

* @param $content html 模板内容

* @return html 替换好的HTML

*/

private function parse_php($content){

if(empty($content)) return false;

$content = preg_replace("/".$this->template_tag_left."(.+?)".$this->template_tag_right."/is", "<?php  $1 ?>", $content);

return $content;

}

/**

* if判断语句

*

* zhang

*

* liang

*

* zhangliang

*

*/

private function parse_if($content) {

if(empty($content)) return false;

//preg_match_all("/".$this->template_tag_left."if\s+(.*?)".$this->template_tag_right."/is", $content, $match);

$match = $this->preg_match_all("if\s+(.*?)", $content);

if(!isset($match[1]) || !is_array($match[1])) return $content;

foreach($match[1] as $k => $v) {

//$s = preg_split("/\s+/is", $v);

//$s = array_filter($s);

$content = str_replace($match[0][$k], "<?php  if({$v}) { ?>", $content);

}

return $content;

}

private function parse_elseif($content) {

if(empty($content)) return false;

//preg_match_all("/".$this->template_tag_left."elseif\s+(.*?)".$this->template_tag_right."/is", $content, $match);

$match = $this->preg_match_all("elseif\s+(.*?)", $content);

if(!isset($match[1]) || !is_array($match[1])) return $content;

foreach($match[1] as $k => $v) {

//$s = preg_split("/\s+/is", $v);

//$s = array_filter($s);

$content = str_replace($match[0][$k], "<?php  } elseif ({$v}) { ?>", $content);

}

return $content;

}

/**

* 解析 include include标签不是实时更新的 当主体文件更新的时候 才更新标签内容,所以想include生效 请修改一下主体文件

* 记录一下 有时间开发一个当DEBUG模式的时候 每次执行删除模版编译文件

* 使用方法

* @param $content 模板内容

* @return html

*/

private function parse_include($content) {

if(empty($content)) return false;

//preg_match_all("/".$this->template_tag_left."include\s+(.*?)".$this->template_tag_right."/is", $content, $match);

$match = $this->preg_match_all("include\s+(.*?)", $content);

if(!isset($match[1]) || !is_array($match[1])) return $content;

foreach($match[1] as $match_key => $match_value) {

$a = preg_split("/\s+/is", $match_value);

$new_tag = array();

//分析元素

foreach($a as $t) {

$b = explode('=', $t);

if(in_array($b[0], $this->tag_include)) {

if(!empty($b[1])) {

$new_tag[$b[0]] = str_replace("\"", "", $b[1]);

} else {

core::show_error('模板路径不存在!');

}

}

}

extract($new_tag);

//查询模板文件

foreach($this->conf['view_path'] as $v){

$conf_view_tpl = $v.$file;//include 模板文件

if(is_file($conf_view_tpl)) {

$c = $this->read_file($conf_view_tpl);

$inc_file = str_replace($this->_tpl_suffix, '', basename($file));

$this->view_path_param = dirname($file).'/';

$compile_dirpath = $this->check_temp_compile();

$include_file = $this->template_replace($c, $compile_dirpath, $inc_file);//解析

break;

} else {

core::show_error('模板文件不存在,请仔细检查 文件:'. $conf_view_tpl);

}

}

$content = str_replace($match[0][$match_key], '<?php  include("'.$include_file.'")?>', $content);

}

return $content;

}

/**

* 解析 foreach

* 使用方法

* @param $content 模板内容

* @return html 解析后的内容

*/

private function parse_foreach($content) {

if(empty($content)) return false;

//preg_match_all("/".$this->template_tag_left."foreach\s+(.*?)".$this->template_tag_right."/is", $content, $match);

$match = $this->preg_match_all("foreach\s+(.*?)", $content);

if(!isset($match[1]) || !is_array($match[1])) return $content;

foreach($match[1] as $match_key => $value) {

$split = preg_split("/\s+/is", $value);

$split = array_filter($split);

$new_tag = array();

foreach($split as $v) {

$a = explode("=", $v);

if(in_array($a[0], $this->tag_foreach)) {//此处过滤标签 不存在过滤

$new_tag[$a[0]] = $a[1];

}

}

$key = '';

extract($new_tag);

$key = ($key) ? '$'.$key.' =>' : '' ;

$s = '<?php  foreach('.$from.' as '.$key.' $'.$item.') { ?>';

$content = $this->str_replace($match[0][$match_key], $s, $content);

}

return $content;

}

/**

* 匹配结束 字符串

*/

private function parse_comm($content) {

$search = array(

"/".$this->template_tag_left."\/foreach".$this->template_tag_right."/is",

"/".$this->template_tag_left."\/if".$this->template_tag_right."/is",

"/".$this->template_tag_left."else".$this->template_tag_right."/is",

);

$replace = array(

"<?php  } ?>",

"<?php  } ?>",

"<?php  } else { ?>"

);

$content = preg_replace($search, $replace, $content);

return $content;

}

/**

* 检查编译目录 如果没有创建 则递归创建目录

* @param string $path 文件完整路径

* @return 模板内容

*/

private function check_temp_compile() {

//$paht = $this->template_c.

$tpl_path = ($this->view_path_param) ? $this->view_path_param : $this->get_tpl_path() ;

$all_tpl_apth = $this->template_c.$tpl_path;

if(!is_dir($all_tpl_apth)) {

$this->create_dir($tpl_path);

}

return $all_tpl_apth;

}

/**

* 读文件

* @param string $path 文件完整路径

* @return 模板内容

*/

private function read_file($path) {

//$this->check_file_limits($path, 'r');

if(($r = @fopen($path, 'r')) === false) {

core::show_error('模版文件没有读取或执行权限,请检查!');

}

$content = fread($r, filesize($path));

fclose($r);

return $content;

}

/**

* 写文件

* @param string $filename 文件名

* @param string $content 模板内容

* @return 文件名

*/

private function compile_file($filename, $content, $dir) {

if(empty($filename)) core::show_error("{$filename} Creation failed");

$content = $this->body_content($content);//对文件内容操作

//echo '开始编译了=====';

$f = $dir.$filename.$this->tpl_compile_suffix;

//$this->check_file_limits($f, 'w');

if(($fp = @fopen($f, 'wb')) === false) {

core::show_error($f.'
编译文件失败,请检查文件权限.');

}

//开启flock

flock($fp, LOCK_EX + LOCK_NB);

fwrite($fp, $content, strlen($content));

flock($fp, LOCK_UN + LOCK_NB);

fclose($fp);

return $f;

}

/**

* 这个检查文件权限函数 暂时废弃了

* @param [$path] [路径]

* @param [status] [w=write, r=read]

*/

public function check_file_limits($path , $status = 'rw') {

clearstatcache();

if(!is_writable($path) && $status == 'w') {

core::show_error("{$path}
没有写入权限,请检查.");

} elseif(!is_readable($path) && $status == 'r') {

core::show_error("{$path}
没有读取权限,请检查.");

} elseif($status == 'rw') {//check wirte and read

if(!is_writable($path) || !is_readable($path)) {

core::show_error("{$path}
没有写入或读取权限,请检查");

}

}

}

/**

* 读取编译后模板的第一行 并分析成数组

* @param string $filepath 文件路径

* @param number $line  行数

* @return 返回指定行数的字符串

*/

/*

private function get_compile_header($filepath, $line = 0) {

if(($file_arr = @file($filepath)) === false) {

core::show_error($filepath.'
读取文件失败,请检查文件权限!');

}

return $file_arr[0];

}

*/

/**

* 分析头部注释的日期

* @param string $cotnent 编译文件头部第一行

* @return 返回上一次日期

*/

/*

private function get_compile_header_comment($content) {

preg_match("/\/\*(.*?)\*\//", $content, $match);

if(!isset($match[1]) || empty($match[1])) core::show_error('编译错误!');

$arr = explode('|', $match[1]);

$arr_date = explode('##', $arr[0]);

return $arr_date[1];

}

*/

/**

* 获取模板完整路径 并返回已存在文件

* @param string $filename 文件名

* @param string $view_path 模板路径

* @return

*/

private function get_tpl($filename, $view_path) {

empty($filename) && $filename = $this->tpl_name;

//遍历模板路径

foreach($this->conf['view_path'] as $path) {

if($view_path) {//直接从tpl跟目录找文件

$tpl_path = $path.$view_path;

$view_file_path = $tpl_path.$filename.$this->_tpl_suffix;

} else {//根据目录,控制器,方法开始找文件

$view_file_path = ($tpl_path = $this->get_tpl_path($path)) ? $tpl_path.$filename.$this->_tpl_suffix : exit(0);

}

if(is_file($view_file_path)) {

//向指针传送模板路径和模板名称

$this->template_path = $tpl_path;//

$this->template_name = $filename.$this->_tpl_suffix;

return true;

} else {

core::show_error($filename.$this->_tpl_suffix.'模板不存在');

}

}

}

/**

* 获取模板路径

* @param string $path 主目录

* @return URL D和M的拼接路径

*/

private function get_tpl_path($path = '') {

core::get_directory_name() && $path_arr[0] = core::get_directory_name();

core::get_controller_name() && $path_arr[1] = core::get_controller_name();

(is_array($path_arr)) ? $newpath = implode('/', $path_arr) : core::show_error('获取模板路径失败!') ;

return $path.$newpath.'/';

}

/**

* 创建目录

* @param string $path 目录

* @return

*/

private function create_dir($path, $mode = 0777){

if(is_dir($path)) return false;

$dir_arr = explode('/', $path);

$dir_arr = array_filter($dir_arr);

$allpath = '';

$newdir = $this->template_c;

foreach($dir_arr as $dir) {

$allpath = $newdir.'/'.$dir;

if(!is_dir($allpath)) {

$newdir = $allpath;

if(!@mkdir($allpath, $mode)) {

core::show_error( $allpath.'
创建目录失败,请检查是否有可都写权限!');

}

chmod($allpath, $mode);

} else {

$newdir = $allpath;

}

}

return true;

}

public function __destruct(){

$this->vars = null;

$this->view_path_param = null;

}

}

更多关于PHP模板解析类实例请关注PHP中文网(www.php.cn)其他文章!

PHP模板解析对象,PHP模板解析类实例相关推荐

  1. json解析对象时指定解析_不解析,使用解析对象

    json解析对象时指定解析 将面向对象的后端与外部系统集成的传统方式是通过数据传输对象 ,这些对象在外出之前先序列化为JSON,然后在返回时反序列化. 这种方法很流行,而且是错误的. 序列化部分应该由 ...

  2. php解析xml数据格式,PHP解析xml格式数据工具类实例分享

    本文主要介绍了PHP解析xml格式数据工具类,涉及php针对xml格式数据节点添加.获取.解析等相关操作技巧,需要的朋友可以参考下,希望能帮助到大家. 本文实例讲述了PHP解析xml格式数据工具类.分 ...

  3. android的cantext对象,安卓Android Context类实例详解

    1.例如下面的代码片段,Toast类的第一个参数接受一个Context对象: @Override protected Dialog onCreateDialog(int id) { switch (i ...

  4. C++模板剖析:函数模板、类模板解析

    C++中关于模板&泛型编程问题:   问题引入:何编写一个通用加法函数? (1)使用函数重载,针对每个所需相同行为的不同类型重新实现它 int Add(const int &_iLef ...

  5. 【Vue源码解析】mustache模板引擎

    模板引擎 什么是模板引擎 实现 Scanner 类 根据模板字符串生成 tokens 在 index.js 引入 parseTemplateToTokens 实现 tokens 的嵌套 One Mor ...

  6. 【Vue.js源码解析 三】-- 模板编译和组件化

    前言 笔记来源:拉勾教育 大前端高薪训练营 阅读建议:建议通过左侧导航栏进行阅读 模板编译 模板编译的主要目的是将模板 (template) 转换为渲染函数 (render) <div> ...

  7. php正则循环,PHP正则解析多重循环模板示例

    本文实例讲述了PHP正则解析多重循环模板.分享给大家供大家参考,具体如下: $str = "客户您好,为您推荐以下项目:(crm{项目2:项目名称} (crm{项目3:项目名称}crm) c ...

  8. tp部署了admin.php如何显示页面,深度解析ThinkPHP5设置模板路径

    本篇文章介绍了thinkphp设置前端模板路径和后台模板路径的方法,具有一定的参考价值,希望对学习thinkPHP的朋友有帮助! 深度解析ThinkPHP5设置模板路径 默认的模板路径在模块/view ...

  9. 类和对象(类是构建对象的模板)

    Java程序运行过程 1.Person.java编译为Person.class文件 2.Test.java编译为Test.class文件 3.main()方法是程序的入口,进入栈区 4.Person ...

最新文章

  1. 《CDN 之我见》原理篇——CDN的由来与调度
  2. 【Codeforces 851D Arpa and a list of numbers】
  3. Python容器专题 - deque(队列)--双向队列对象
  4. 【NLP】doc2vec原理及实践
  5. java-线程同步问题
  6. 输出一行数字,中间用空格隔开,最后一个数字没有空格
  7. 支付宝接口报错 insufficient-isv-permissions 错误原因: ISV权限不足解决方案
  8. Android 最常用的设计模式一 安卓源码分析—单例模式singleInstance
  9. DL/T645-2007通信协议应用层学习记录
  10. 这是一篇随笔 hello world
  11. R语言进行人年发病率可信区间计算(per 1,000 person-years)
  12. 每日一书丨这本书献给所有铸就开源世界的人们
  13. CCF-CSP201809-4 再卖菜
  14. Regin恶意软件:何以潜伏如此久?
  15. 计算机ip地址在哪找,如何查ip地址,电脑ip地址在哪看
  16. ListView控件和Adapter
  17. Guide哥连夜赶的7000+字的Spring事务总结来啦!我饱了!
  18. 【Linux入门学习笔记】Linux命令查阅方法及文件操作命令简介
  19. 了解公司企业:Intuit
  20. 聚乙烯亚胺(PEI)超细纤维负载Pd纳米粒子,GA-PEG-PLA 甘草次酸-聚乙二醇-聚乳酸定制合成

热门文章

  1. 楼中楼应该怎么写 php,什么是楼中楼?楼中楼怎么样?
  2. python三个箭头怎么打出来_IntelliJ IDEA 调试真香技巧
  3. Carsim车辆动力学模型:轮胎
  4. 编码开关的原理及使用方法
  5. 自己收藏:魔鬼在细节中
  6. python浪漫文艺_有哪些文艺到爆炸的句子?
  7. Mentor-dft 学习笔记 day20-ATPG Event Simulation for DFFs and Latches
  8. 城市自来水公司生产过程自动化监控系统(原创)
  9. uniapp 判断字符串中是否包含表情
  10. odoo owl解释