PHP template parsing class
-
- class template {
- private $vars = array();
- private $conf = '';
- private $tpl_name = 'index';//If the template does not exist, the current controller will be searched Default index template
- private $tpl_suffix = '.html';//If CONFIG is not configured with a default suffix, it will be displayed
- private $tpl_compile_suffix= '.tpl.php';//Compile template path
- private $template_tag_left = '<{' ;//Template left tag
- private $template_tag_right = '}>';//Template right tag
- private $template_c = '';//Compilation directory
- private $template_path = '';//Template full path
- private $ template_name = '';//Template name index.html
-
-
- //Elements that define the tags of each template
- private $tag_foreach = array('from', 'item', 'key');
- private $tag_include = array('file');//Currently only supports reading the default path of the template
-
- public function __construct($conf) {
- $this->conf = &$conf;
-
- $this->template_c = $this ->conf['template_config']['template_c'];//Compilation directory
- $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 regular
- * @param $content content
- * @return array
- */
-
- private function preg_match_all($pattern, $content) {
- if(empty($pattern) || empty($content)) core::show_error('Failed to find template tag!') ;
- preg_match_all("/".$this->template_tag_left.$pattern.$this->template_tag_right."/is", $content, $match);
- return $match;
- }
- /**
- * Template file suffix
- */
- 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;
- }
-
- /**
- * No explanation here
- * @return
- */
- public function assign($key, $value) {
- $this->vars[$key] = $value;
- }
-
- /**
- * Render page
- * @param
- * Usage method 1
- * $this->view->display('error', 'comm/');
- * The default is to point to the following directory of the TPL template, so comm/ It is tpl/comm/error.html
- * Usage method 2
- * $this->view->display('errorfile');
- * By default, it points to the folder fixed by the controller
- * For example, your domain name is http: //heartphp/admin/index, then the correct path is tpl/admin/index/errorfile.html
- * @return
- */
- public function display($filename = '', $view_path = '') {
- $tpl_path_arr = $this->get_tpl($filename, $view_path );//Get the TPL full path and transfer the path and name to the pointer
- if(!$tpl_path_arr) core::show_error($filename.$this->_tpl_suffix.'Template does not exist');
-
- //Compilation starts
- $this->view_path_param = $view_path;//The template and directory passed by the user
- $this->compile();
-
- }
-
- /**
- * Compile controller
- * @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);//Parse
- 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;
- }
- }
-
- /**
- * Read the current project configuration file
- */
- protected function read_config() {
- if(file_exists(SYSTEM_PATH.'conf/config.php')) {
- @include SYSTEM_PATH.'conf/ config.php';
- return $config;
- }
-
- return false;
- }
- /**
- * Parse template syntax
- * @param $str content
- * @param $compile_dirpath template compilation directory
- * @param $vars_template_c_name template compilation file name
- * @return compiled PHP template file name
- */
- private function template_replace($str, $compile_dirpath, $vars_template_c_name) {
- if(empty($str)) core::show_error('Template content is empty!');
-
- / /Process compilation header
- $compile_path = $compile_dirpath.$vars_template_c_name.$this->tpl_compile_suffix;//Compile file
-
- 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);
- //If the file expires, compile and the template tag has include and is modified. Also recompile
- //<{include file="public/left. html"}> When modifying the files in the include, in non-DEBUG mode, if the main file is not changed, the files in the include are not recompiled at present. I am considering whether to change it as well. I haven't thought about it. This is the case for the time being, so in the development stage Be sure to turn on DEBUG=1 mode, otherwise modifying the include file will be invalid.有点罗嗦,不知道表述清楚没
- 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;
- }
-
-
- /**
- * Template file body
- * @param string $str content
- * @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}*/?>rn$str";
-
- return $content;
- }
-
- /**
- * Start parsing related template tags
- * @param $content template 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;
- }
-
- /**
- * If echo is directly <{$config['domain']}> by default, it will be converted to
- */
- private function parse_echo($content) {
-
- }
-
- /**
- * Convert to PHP
- * @param $content html template content
- * @return html Replaced HTML
- */
- private function parse_php($content){
- if(empty($content)) return false;
- $content = preg_replace("/".$this->template_tag_left."(.+?)".$this->template_tag_right."/is", "", $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."ifs+(.*?)".$this->template_tag_right."/is", $content, $match);
-
- $match = $this->preg_match_all("ifs+(.*?)", $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], "", $content);
- }
-
- return $content;
- }
-
- private function parse_elseif($content) {
- if(empty($content)) return false;
- //preg_match_all("/".$this->template_tag_left."elseifs+(.*?)".$this->template_tag_right."/is", $content, $match);
- $match = $this->preg_match_all("elseifs+(.*?)", $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], "", $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."includes+(.*?)".$this->template_tag_right."/is", $content, $match);
- $match = $this->preg_match_all("includes+(.*?)", $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], '', $content);
- }
-
- return $content;
-
- }
- /**
- * Parse foreach
- * Usage method <{foreach from=$lists item=value key=kk}>
- * @param $content template content
- * @return html parsed content
- */
- private function parse_foreach($content) {
- if(empty($content)) return false;
-
- //preg_match_all("/".$this->template_tag_left."foreachs+(.*?)".$this->template_tag_right."/is", $content, $match);
- $match = $this->preg_match_all("foreachs+(.*?)", $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 = '';
- $content = $this->str_replace($match[0][$match_key], $s, $content);
-
- }
-
- return $content;
- }
-
- /**
- * End of match string
- */
- 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(
- "",
- "",
- ""
- );
- $content = preg_replace($search, $replace, $content);
- return $content;
- }
- /**
- * Check the compilation directory. If it is not created, create the directory recursively
- * @param string $path The full path of the file
- * @return Template content
- */
- 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;
- }
- /**
- * Read file
- * @param string $path The full path of the file
- * @return Template content
- */
- 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;
- }
-
- /**
- * Write file
- * @param string $filename file name
- * @param string $content template content
- * @return file name
- */
- 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;
- }
-
- /**
- * This function to check file permissions is temporarily abandoned
- * @param [$path] [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}
没有写入或读取权限,请检查");
- }
- }
-
-
- }
-
- /**
- * Read the first line of the compiled template and analyze it into an array
- * @param string $filepath file path
- * @param number $line number of lines
- * @return returns a string with the specified number of lines
- */
- /*
- private function get_compile_header($filepath, $line = 0) {
-
- if(($file_arr = @file($filepath)) === false) {
- core::show_error($filepath.'
读取文件失败,请检查文件权限!');
- }
- return $file_arr[0];
- }
- */
-
- /**
- * Date of analysis of header comments
- * @param string $cotnent The first line of the header of the compiled file
- * @return Returns the last date
- */
- /*
- private function get_compile_header_comment($content) {
- preg_match("//*(.* ?)*//", $content, $match);
- if(!isset($match[1]) || empty($match[1])) core::show_error('Compilation error!');
- $arr = explode('|', $match[1]);
- $arr_date = explode('##', $arr[0]);
-
- return $arr_date[1];
- }
- */
- / **
- * Get the full path of the template and return the existing file
- * @param string $filename file name
- * @param string $view_path template path
- * @return
- */
- private function get_tpl($filename, $view_path) {
- empty($filename) && $filename = $this->tpl_name;
-
- //Traverse the template path
- foreach($this-> ;conf['view_path'] as $path) {
- if($view_path) {//Find files directly from tpl and directory
- $tpl_path = $path.$view_path;
- $view_file_path = $tpl_path.$filename.$this ->_tpl_suffix;
- } else {//Start looking for files based on the directory, controller, and method
- $view_file_path = ($tpl_path = $this->get_tpl_path($path)) ? $tpl_path.$filename.$this- >_tpl_suffix : exit(0);
- }
-
- if(is_file($view_file_path)) {
- //Transfer template path and template name to the pointer
- $this->template_path = $tpl_path;//
- $this- >template_name = $filename.$this->_tpl_suffix;
- return true;
- } else {
- core::show_error($filename.$this->_tpl_suffix.'Template does not exist');
- }
- }
- }
-
- /**
- * Get the template path
- * @param string $path Home directory
- * @return URL The splicing path of D and 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('Failed to get template path!') ;
-
- return $path.$newpath.'/';
- }
-
- /**
- * Create directory
- * @param string $path directory
- * @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.'
Failed to create the directory, please check whether you have write permissions! ');
- }
- chmod($allpath, $mode);
- } else {
- $newdir = $allpath;
- }
- }
- return true;
- }
-
- public function __destruct(){
- $this-> vars = null;
- $this->view_path_param = null;
- }
-
- };
Copy code
|