使Web系统的开发与维护更加方便,从而有效的节省人力物力,受到了越来越多企业的青眯。 模板引擎是MVC模式建立过程的重要方法,开发者可以设计一套赋予含义的标签,通过技术解析处理有效的把数据逻辑处理从界面模板中提取出来,通过解读标签的含义把控制权提交给相应业务逻辑处理程序,从而获取到需要的数据,以模板设计的形式展现出来,使设计人员能把精力更多放在表现形式上。下面是我对模板引擎的认识与设计方法: 说的好听些叫模板引擎,实际就是解读模板数据的过程(个人观点^^)。通过我对建站方面的思考认识,网站在展现形式上无非归纳为单条和多条两种形式,那么我们可以设定两种对应标签(如data、list)来处理这两种情况,关键点在于解决两种标签的多层相互嵌套问题,基本适合实现80%界面形式。 解读模板的方法有多种,常用的包括字符串处理(解决嵌套稍麻烦)、正则表达式。在这里我选用的正则表达式,下面是我的处理方法(本文仅提供思路和参考代码,可能不能直接使用)。 模板文件解析类: <div class="codetitle"><a style="CURSOR: pointer" data="79154" class="copybut" id="copybut79154" onclick="doCopy('code79154')"> 代码如下:<div class="codebody" id="code79154"> <?php / class: 模板解析类 author: 51JS.COM-ZMM date: 2011.3.1 email: 304924248@qq.com blog: http://www.cnblogs.com/cnzmm/ / class Template { public $html,$vars,$bTag,$eTag; public $bFlag='{',$eFlag='}',$pfix='zmm:'; private $folder,$file; function __construct($vars=array()) { !empty($vars) && $this->vars = $vars; !empty($GLOBALS['cfg_tag_prefix']) && $this->pfix = $GLOBALS['cfg_tag_prefix'].':'; $this->bTag = $this->bFlag.$this->pfix; $this->eTag = $this->bFlag.'/'.$this->pfix; empty(Tags::$vars) && Tags::$vars = &$this->vars; } public function LoadTpl($tpl) { $this->file = $this->GetTplPath($tpl); Tags::$file = &$this->file; if (is_file($this->file)) { if ($this->GetTplHtml()) { $this->SetTplTags(); } else { exit('模板文件加载失败!'); } } else { exit('模板文件['.$this->file.']不存在!'); } } private function GetTplPath($tpl) { $this->folder = WEBSITE_DIRROOT. $GLOBALS['cfg_tpl_root']; return $this->folder.'/'.$tpl; } private function GetTplHtml() { $html = self::FmtTplHtml(file_get_contents($this->file)); if (!empty($html)) { $callFunc = Tags::$prefix.'Syntax'; $this->html = Tags::$callFunc($html,new Template()); } else { exit('模板文件内容为空!'); } return true; } static public function FmtTplHtml($html) { return preg_replace('/(r)|(n)|(t)|(s{2,})/is','',$html); } public function Register($vars=array()) { if (is_array($vars)) { $this->vars = $vars; Tags::$vars = &$this->vars; } } public function Display($bool=false,$name="",$time=0) { if (!empty($this->html)) { if ($bool && !empty($name)) { if (!is_int($time)) $time = 600; $cache = new Cache($time); $cache->Set($name,$this->html); } echo $this->html; flush(); } else { exit('模板文件内容为空!'); } } public function SetAssign($souc,$info) { if (!empty($this->html)) { $this->html = str_ireplace($souc,self::FmtTplHtml($info),$this->html); } else { exit('模板文件内容为空!'); } } private function SetTplTags() { $this->SetPanelTags(); $this->SetTrunkTags(); $this->RegHatchVars(); } private function SetPanelTags() { $rule = $this->bTag.'([^'.$this->eFlag.']+)/'.$this->eFlag; preg_match_all('/'.$rule.'/ism',$this->html,$out_matches); $this->TransTag($out_matches,'panel'); unset($out_matches); } private function SetTrunkTags() { $rule = $this->bTag.'(w+)s([^'.$this->eFlag.']?)'.$this->eFlag. '((?:(?!'.$this->bTag.')[Ss]?|(?R)))'.$this->eTag.'1s'.$this->eFlag; preg_match_all('/'.$rule.'/ism','trunk'); unset($out_matches); } private function TransTag($result,$type) { if (!empty($result[0])) { switch ($type) { case 'panel' : { for ($i = 0; $i < count($result[0]); $i ++) { $strTag = explode(' ',$result[1][$i],2); if (strpos($strTag[0],'.')) { $itemArg = explode('.',2); $callFunc = Tags::$prefix.ucfirst($itemArg[0]); if (method_exists('Tags',$callFunc)) { $html = Tags::$callFunc(chop($itemArg[1])); if ($html !== false) { $this->html = str_ireplace($result[0][$i],$html,$this->html); } } } else { $rule = '^([^s]+)s([Ss]+)$'; preg_match_all('/'.$rule.'/is',trim($result[1][$i]),$tmp_matches); $callFunc = Tags::$prefix.ucfirst($tmp_matches[1][0]); if (method_exists('Tags',$callFunc)) { $html = Tags::$callFunc($tmp_matches[2][0]); if ($html !== false) { $this->html = str_ireplace($result[0][$i],$this->html); } } unset($tmp_matches); } } break; } case 'trunk' : { for ($i = 0; $i < count($result[0]); $i ++) { $callFunc = Tags::$prefix.ucfirst($result[1][$i]); if (method_exists('Tags',$callFunc)) { $html = Tags::$callFunc($result[2][$i],$result[3][$i]); $this->html = str_ireplace($result[0][$i],$this->html); } } break; } default: break; } } else { return false; } } private function RegHatchVars() { $this->SetPanelTags(); } function __destruct() {} } ?>
标签解析类:(目前暂时提供data、list两种标签的解析,说明思路) <div class="codetitle"><a style="CURSOR: pointer" data="70868" class="copybut" id="copybut70868" onclick="doCopy('code70868')"> 代码如下:<div class="codebody" id="code70868"> <?php / class: 标签解析类 author: 51JS.COM-ZMM date: 2011.3.2 email: 304924248@qq.com blog: http://www.cnblogs.com/cnzmm/ / class Tags { static private $attrs=null; static public $file,$rule,$prefix='TAG_'; static public function TAG_Syntax($html,$that) { $rule = $that->bTag.'ifs+([^'.$that->eFlag.']+)s'.$that->eFlag; $html = preg_replace('/'.$rule.'/ism','<?php if (1) { ?>',$html); $rule = $that->bTag.'elseifs+([^'.$that->eFlag.']+)s'.$that->eFlag; $html = preg_replace('/'.$rule.'/ism','<?php } elseif (1) { ?>',$html); $rule = $that->bTag.'elses'.$that->eFlag; $html = preg_replace('/'.$rule.'/ism','<?php } else { ?>',$html); $rule = $that->bTag.'loops+(S+)s+(S+)s'.$that->eFlag; $html = preg_replace('/'.$rule.'/ism','<?php foreach (1 as 2) { ?>',$html); $rule = $that->bTag.'loops+(S+)s+(S+)s+(S+)s'.$that->eFlag; $html = preg_replace('/'.$rule.'/ism','<?php foreach (1 as 2 => 3) { ?>',$html); $rule = $that->eTag.'(if|loop)s'.$that->eFlag; $html = preg_replace('/'.$rule.'/ism','<?php } ?>',$html); $rule = $that->bTag.'phps'.$that->eFlag.'((?:(?!'. $that->bTag.')[Ss]?|(?R)))'.$that->eTag.'phps'.$that->eFlag; $html = preg_replace('/'.$rule.'/ism','<?php 1 ?>',$html); return self::TAG_Execute($html); } static public function TAG_List($attr,$html) { if (!empty($html)) { if (self::TAG_HaveTag($html)) { return self::TAG_DealTag($attr,true); } else { return self::TAG_GetData($attr,true); } } else { exit('标签{list}的内容为空!'); } } static public function TAG_Data($attr,false); } else { return self::TAG_GetData($attr,false); } } else { exit('标签{data}的内容为空!'); } } static public function TAG_Execute($html) { ob_clean(); ob_start(); if (!empty(self::$vars)) { is_array(self::$vars) && extract(self::$vars,EXTR_OVERWRITE); } $file_inc = WEBSITE_DIRINC.'/buffer/'. md5(uniqid(rand(),true)).'.php'; if ($fp = fopen($file_inc,'xb')) { fwrite($fp,$html); if (fclose($fp)) { include($file_inc); $html = ob_get_contents(); } unset($fp); } else { exit('模板解析文件生成失败!'); } ob_end_clean(); @unlink($file_inc); return $html; } static private function TAG_HaveTag($html) { $bool_has = false; $tpl_ins = new Template(); self::$rule = $tpl_ins->bTag.'([^'.$tpl_ins->eFlag.']+)/'.$tpl_ins->eFlag; $bool_has = $bool_has || preg_match('/'.self::$rule.'/ism',$html); self::$rule = $tpl_ins->bTag.'(w+)s([^'.$tpl_ins->eFlag.']?)'.$tpl_ins->eFlag. '((?:(?!'.$tpl_ins->bTag.')[Ss]?|(?R)))'.$tpl_ins->eTag.'1s'.$tpl_ins->eFlag; $bool_has = $bool_has || preg_match('/'.self::$rule.'/ism',$html); unset($tpl_ins); return $bool_has; } static private function TAG_DealTag($attr,$list) { preg_match_all('/'.self::$rule.'/ism',$out_matches); if (!empty($out_matches[0])) { $child_node = array(); for ($i = 0; $i < count($out_matches[0]); $i ++) { $child_node[] = $out_matches[3][$i]; $html = str_ireplace($out_matches[3][$i],'{-->>childnode'.$i.'<<--}',$html); } $html = self::TAG_GetData($attr,$list); for ($i = 0; $i < count($out_matches[0]); $i ++) { $html = str_ireplace('{-->>childnode'.$i.'<<--}',$child_node[$i],$html); } preg_match_all('/'.self::$rule.'/ism',$tmp_matches); if (!empty($tmp_matches[0])) { for ($i = 0; $i < count($tmp_matches[0]); $i ++) { $callFunc = self::$prefix.ucfirst($tmp_matches[1][$i]); if (method_exists('Tags',$callFunc)) { $temp = self::$callFunc($tmp_matches[2][$i],$tmp_matches[3][$i]); $html = str_ireplace($tmp_matches[0][$i],$temp,$html); } } } unset($tmp_matches); } unset($out_matches); return $html; } static private function TAG_GetData($attr,$list=false) { if (!empty($attr)) { $attr_ins = new Attbt($attr); $attr_arr = $attr_ins->attrs; if (is_array($attr_arr)) { extract($attr_arr,EXTR_OVERWRITE); $source = table_name($source,$column); $rule = '[field:s(w+)s([^]]?)s/?]'; preg_match_all('/'.$rule.'/is',$out_matches); $data_str = ''; $data_ins = new DataSql(); $attr_where = $attr_order = ''; if (!empty($where)) { $where = str_replace(',',' and ',$where); $attr_where = ' where '. $where; } if (!empty($order)) { $attr_order = ' order by '.$order; } else { $fed_name = ''; $fed_ins = $data_ins->GetFedNeedle($source); $fed_cnt = $data_ins->GetFedCount($fed_ins); for ($i = 0; $i < $fed_cnt; $i ++) { $fed_flag = $data_ins->GetFedFlag($fed_ins,$i); if (preg_match('/auto_increment/ism',$fed_flag)) { $fed_name = $data_ins->GetFedName($fed_ins,$i); break; } } if (!empty($fed_name)) $attr_order = ' order by '.$fed_name.' desc'; } if ($list == true) { if (empty($source) && empty($sql)) { exit('标签{list}必须指定source属性!'); } $attr_rows = $attr_page = ''; if ($rows > 0) { $attr_rows = ' limit 0,'.$rows; } if (!empty($sql)) { $data_sql = $sql; } else { $data_sql = 'select from '.$source.' '. $attr_where.$attr_order.$attr_rows; } if ($pages=='true' && !empty($size)) { $data_num = $data_ins->GetRecNum($data_sql); $page_cnt = ceil($data_num / $size); global $page; if (!isset($page) || $page < 1) $page = 1; if ($page > $page_cnt) $page = $page_cnt; $data_sql = 'select from '.$source.' '.$attr_where. $attr_order.' limit '.($page-1) $size.','.$size; $GLOBALS['cfg_page_curr'] = $page; $GLOBALS['cfg_page_prev'] = $page - 1; $GLOBALS['cfg_page_next'] = $page + 1; $GLOBALS['cfg_page_nums'] = $page_cnt; if (function_exists('list_pagelink')) { $GLOBALS['cfg_page_list'] = list_pagelink($page,$page_cnt,2); } } $data_idx = 0; $data_ret = $data_ins->SqlCmdExec($data_sql); while ($row = $data_ins->GetRecArr($data_ret)) { if ($skip > 0 && !empty($flag)) { $data_idx != 0 && $data_idx % $skip == 0 && $data_str .= $flag; } $data_tmp = $html; $data_tmp = str_ireplace('@idx',$data_idx,$data_tmp); for ($i = 0; $i < count($out_matches[0]); $i ++) { $data_tmp = str_ireplace($out_matches[0][$i], $row[$out_matches[1][$i]],$data_tmp); } $data_str .= $data_tmp; $data_idx ++; } } else { if (empty($source)) { exit('标签{data}必须指定source属性!'); } $data_sql = 'select * from '.$source. <BR>' '.$attr_where.$attr_order; $row = $data_ins->GetOneRec($data_sql); if (is_array($row)) { $data_tmp = $html; for ($i = 0; $i < count($out_matches[0]); $i ++) { $data_val = $row[$out_matches[1][$i]]; if (empty($out_matches[2][$i])) { $data_tmp = str_ireplace($out_matches[0][$i],$data_val,$data_tmp); } else { $attr_str = $out_matches[2][$i]; $attr_ins = new Attbt($attr_str); $func_txt = $attr_ins->attrs['function']; if (!empty($func_txt)) { $func_tmp = explode('(',$func_txt); if (function_exists($func_tmp[0])) { eval('$func_ret ='.str_ireplace('@me', '''.$data_val.''',$func_txt)); $data_tmp = str_ireplace($out_matches[0][$i],$func_ret,$data_tmp); } else { exit('调用了不存在的函数!'); } } else { exit('标签设置属性无效!'); } } } $data_str .= $data_tmp; } } unset($data_ins); return $data_str; } else { exit('标签设置属性无效!'); } } else { exit('没有设置标签属性!'); } } static public function __callStatic($name,$args) { exit('标签{'.$name.'}不存在!'); } } ?>
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|