首页 > 编程 > PHP > 正文

PHP模板解析类实例

2020-03-22 18:29:23
字体:
来源:转载
供稿:网友
//如果模板不存在 会查找当前 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 = $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).' br/ //echo $compile_filemtime.'=='.date('Y-m-d H:i:s', $compile_filemtime); //如果文件过期编译 当模板标签有include并且有修改时 也重新编译 // {include file="public/left.html"} 当修改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 如果默认直接 {$config['domain']} 转成 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判断语句 * {if empty($zhang)} * zhang * {elseif empty($liang)} * liang * {else} * zhangliang * {/if} 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模式的时候 每次执行删除模版编译文件 * 使用方法 {include file="www.phpddt.com"} * @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 * 使用方法 {foreach from=$lists item=value key=kk} * @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.' br/ 编译文件失败,请检查文件权限.'); //开启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} br/ 没有写入权限,请检查."); } elseif(!is_readable($path) && $status == 'r') { core::show_error("{$path} br/ 没有读取权限,请检查."); } elseif($status == 'rw') {//check wirte and read if(!is_writable($path) || !is_readable($path)) { core::show_error("{$path} br/ 没有写入或读取权限,请检查"); * 读取编译后模板的第一行 并分析成数组 * @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.' br/ 读取文件失败,请检查文件权限!'); 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.' br/ 创建目录失败,请检查是否有可都写权限!'); chmod($allpath, $mode); } else { $newdir = $allpath; return true; public function __destruct(){ $this- vars = null; $this- view_path_param = null;}希望本文所述对大家的php程序设计有所帮助。PHP教程

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表