编写模板类三步曲.docx
- 文档编号:30500626
- 上传时间:2023-08-16
- 格式:DOCX
- 页数:23
- 大小:23.25KB
编写模板类三步曲.docx
《编写模板类三步曲.docx》由会员分享,可在线阅读,更多相关《编写模板类三步曲.docx(23页珍藏版)》请在冰豆网上搜索。
编写模板类三步曲
一:
php
define('TPL_DIR','./templates/');
define('TPL_C_DIR','./templates_c/');
classStupid{
private$_tpl_vars;
private$_tpl_file;
private$_parser;
private$_debug;
publicfunctionStupid(){
if(!
is_dir(TPL_DIR)||!
is_dir(TPL_C_DIR)){
exit('错误:
请正确设置模板文件夹和编译文件夹');
}
}
publicfunctionassign($var,$value){
if(isset($var)&&trim($var)!
=''){
$this->_tpl_vars[$var]=$value;
returntrue;
}else{
exit('错误:
请设置变量名');
}
}
publicfunctiondisplay($tpl_file){
$template_file=TPL_DIR.$tpl_file;
if(!
file_exists($template_file)){
exit('错误:
模板文件不存在');
}
$parsed_file=TPL_C_DIR.md5($tpl_file).'.php';
if(!
file_exists($parsed_file)||filemtime($parsed_file) require_once'./stupid_parser.class.php'; $this->_parser=newStupidParser(); $this->_parser->compile($tpl_file); } include$parsed_file; } functiondebug($tpl_file){ if(include_once("stupid_debugger.class.php")){ $this->_debugger=newStupidDebugger($tpl_file); $this->_debugger->start(); }else{ exit('错误: Debuger类文件不存在'); } } } ? > [ 本帖最后由liexusong于2008-12-2413: 58编辑 ] liexusong (2008-11-3016: 38: 10) 第二篇编译篇(转载请注明: phpchina毛毛虫) 新建文件stupid_parser.class.php。 先定义我们的类StupidParser: php classStupidParser{ } 我们这个只要一个成员变量就可以了,就是$template,他是用来保存模板的内容的。 php classStupidParser{ private$template; } 我们先写个set_file()的方法吧,他是用来设置和读取模板文件的。 privatefunctionset_file($file){ $file=TPL_DIR.$file; if(! file_exists($file)){ exit('错误: 模板文件不存在'); } $fp=fopen($file,'r'); if(! $fp)exit('错误: 不能打开文件'); if(filesize($file)){ $this->template=fread($fp,filesize($file)); }else{ exit('错误: 模板文件大小为零'); } fclose($fp); returntrue; } 这个方法主要是检测模板文件存不存在和读取模板文件的内容,并把内容放置到成员变量$template中。 --------------------------------------------------------------------------------------------- 好了,现在我们定义我们的模板规则吧: 1.匹配变量的模式: {$var_name} 2.匹配条件的模式: {ifcondition}.....................{/if} 3.匹配注释的模式: {#}.......................................{#} 4.匹配包含文件的模式: {include"file_name"} 5.匹配foreach的模式(循环数组): {$array_name->foreach(key,value)}....................{/foreach} 6.foreach中的变量表示: {@key}{@value} -------------------------------------------------------------------------------------------- 1.先来写个解析变量的方法吧: privatefunction_parse_var(){ $patten="/\{\\$([a-zA-Z0-9_]+)\}/"; if(strpos($this->template,'{$')! ==false){ $this->template=preg_replace($patten," phpecho\$this->_tpl_vars['$1'];? >",$this->template); } returntrue; } 这个方法是用来匹配{$var_name}这种模式的,即匹配以大括号包含着变量的模式,我们把他替换成 phpecho$var_name;? >这种模式。 我们是用/\{\\$([a-zA-Z0-9_]+)\}/这样的正则表达式来匹配的,\{这个是匹配大括号的左边,\\$这个是匹配美元符号,([a-zA-Z0-9_]+)这个是匹配以数字字符或者下划线组成的字符串,\}这个是匹配大括号的右边。 替换完之后,我们把他存放到$this->template成员变量中。 2.接着写解析IF条件语句的方法: [php] privatefunction_parse_if(){ if(preg_match("/\{\s*if/",$this->template)){ if(preg_match('/\{\s*\/if\s*\}/',$this->template)){ $if_patten="/\{\s*if\s+([^}]+)\}/"; $ef_patten="/\{\s*\/if\s*\}/"; $this->template=preg_replace($if_patten," phpif($1): ? >",$this->template); $this->template=preg_replace($ef_patten," phpendif;? >",$this->template); }else{ exit('错误: 语法错误,没有封闭IF条件语句'); } } returntrue; } [/php] 方法的开始用了if(preg_match("/\{\s*if/",$this->template))这个判断是否存在IF语句,存在我们才去编译他。 /\{\s*if/这个模式是匹配{if或者{if的形式。 存在这种形式,我们就用if(preg_match('/\{\s*\/if\s*\}/',$this->template))判断是否存在{/if}这种形式,不存在就说明语法错误(没有封闭IF语句),我们就给个错误消息。 这两个条件都成立的话,我们就开始编译了。 把{if.......}换成 phpif(......): ? >,把{/if}换成 phpendif;? >。 再保存到$this->template成员变量中。 这样我们就编译完IF条件语句了~ 注释语句的编译: privatefunction_parse_common(){ $patten="/\{#\}([^{]*)\{#\}/"; if(strpos($this->template,'{#}')! ==false){ $this->template=preg_replace($patten," php/*$1*/? >",$this->template); } returntrue; } 注释语句是这样({#}...............................{#})的模式,把两个{#}之间的内容注释了。 所以我们先用if(strpos($this->template,'{#}')! ==false)来判断是否存在注释语句,存在我们就编译他。 /\{#\}([^{]*)\{#\}/正则表达式就是用来编译{#}...............................{#}这种模式为 php/*.......................*/? >的。 编译Include: [php] privatefunction_parse_include(){ if(preg_match("/\{\s*include\"([^}]*)\"\s*\}/",$this->template,$file)){ if(trim($file[1])=='')exit('错误: 必须指定包含的文件'); if(! file_exists(trim($file[1])))exit('错误: 文件不存在'); $include_patten='/{\s*include"([^}]+)"\s*}/'; $this->template=preg_replace($include_patten," phpinclude'$1';? >",$this->template); } returntrue; } [/php] 其实include语句也很简单,我们要匹配的是{include"file_$ame"}这种模式,所以我们先用preg_match("/\{\s*include\"([^}]*)\"\s*\}/",$this->template,$file)来把所有的include文件都找出来,然后用if(trim($file[1])=='')和if(! file_exists(trim($file[1]))这两句来判断文件是否存在。 存在我们再去编译他。 然后我们就把{include"file_name"}替换成 phpinclude"file_name";? >这种形式。 再保存到$this->template成员变量中。 编译foreach语句: [php] privatefunction_parse_foreach(){ if(preg_match("/\{\s*\\$[0-9a-zA-Z_]+\s*->\s*foreach/",$this->template)){ if(preg_match("/{\s*\/foreach\s*}/",$this->template)){ if(preg_match("/\{\s*@[0-9a-zA-Z_]+/",$this->template)){ $k_and_v_patten="/\{\s*@([0-9a-zA-Z_]+)\s*\}/"; $this->template=preg_replace($k_and_v_patten," phpecho\$$1;? >",$this->template); } $foreach_patten="/\{\s*\\$([0-9a-zA-Z_]+)\s*->\s*foreach\(\s*([0-9a-zA-Z_]+)\s*,\s*([0-9a-zA-Z_]+)\s*\)\s*\}/"; $end_foreach_patten="/\{\s*\/foreach\s*\}/"; $this->template=preg_replace($foreach_patten," phpforeach(\$this->_tpl_vars['$1']as\$$2=>\$$3): ? >",$this->template); $this->template=preg_replace($end_foreach_patten," phpendforeach;? >",$this->template); }else{ exit('错误: 语法错误,没有封闭FOREACH条件语句'); } } } [/php] Foreach语句是最复杂的。 我们要匹配的是{$array_name->foreach(key,value)}....................{/foreach}这种模式,$array_name是数组名,key和value是键和值。 就好像php中的foreach($array_nameas$key=>$value)一样,我们就是要把前面的换成后面的形式。 我们先用if(preg_match("/\{\s*\\$[0-9a-zA-Z_]+\s*->\s*foreach/",$this->template))和if(preg_match("/{\s*\/foreach\s*}/",$this->template))来判断是否存在foreach语句和是否闭合了foreach语句。 存在的话我们就用$foreach_patten和$end_foreach_patten这两个正则表达式来替换{$array_name->foreach(key,value)}这种形式为 phpforeach($array_nameas$key=>$value): ? >,替换{/foreach}问 phpendforeach;? >。 我们会发现代码中有个if(preg_match("/\{\s*@[0-9a-zA-Z_]+/",$this->template))这样的判断,这个是判断是否存在{@key}这种形式的,这个是个上面的key相关的,编译之后会替换成 phpecho$key;? >这种形式。 好了,5条语句的编译方法都写好了。 现在就写compile方法,他是调用我们刚才写的解析方法和写入编译之后的文件的: [php] publicfunctioncompile($file_name){ $this->set_file($file_name); $this->_parse_var(); $this->_parse_if(); $this->_parse_common(); $this->_parse_foreach(); $this->_parse_include(); $tpl_c_file=TPL_C_DIR.md5(basename($file_name)).'.php'; $fp=fopen($tpl_c_file,'w'); fwrite($fp,$this->template); fclose($fp); } [/php] $tpl_c_file=TPL_C_DIR.md5(basename($file_name)).'.php'这句是生产编译之后的文件名。 我们使用了MD5来取得一个唯一的名字。 假如你觉得不好的话,可以自己改一下。 最后就把解析完之后的$this->template写入文件了! 好了,这个编译类,我们就讲完了,有什么不懂可以跟帖提出。 下次就说说调试类的编写,请继续支持。 最后showshow全相: [php] php classStupidParser{ private$template; privatefunctionset_file($file){ $file=TPL_DIR.$file; if(! file_exists($file)){ exit('错误: 模板文件不存在'); } $fp=fopen($file,'r'); if(! $fp)exit('错误: 不能打开文件'); if(filesize($file)){ $this->template=fread($fp,filesize($file)); }else{ exit('错误: 模板文件大小为零'); } fclose($fp); returntrue; } publicfunctioncompile($file_name){ $this->set_file($file_name); $this->_parse_var(); $this->_parse_if(); $this->_parse_common(); $this->_parse_foreach(); $this->_parse_include(); $tpl_c_file=TPL_C_DIR.md5(basename($file_name)).'.php'; $fp=fopen($tpl_c_file,'w'); fwrite($fp,$this->template); fclose($fp); } privatefunction_parse_var(){ $patten="/\{\\$([a-zA-Z0-9_]{1,})\}/"; if(strpos($this->template,'{$')! ==false){ $this->template=preg_replace($patten," phpecho\$this->_tpl_vars['$1'];? >",$this->template); } returntrue; } privatefunction_parse_if(){ if(preg_match("/\{\s*if/",$this->template)){ if(preg_match('/\{\s*\/if\s*\}/',$this->template)){ $if_patten="/\{\s*if\s+([^}]+)\}/"; $ef_patten="/\{\s*\/if\s*\}/"; $this->template=preg_replace($if_patten," phpif($1): ? >",$this->template); $this->template=preg_replace($ef_patten," phpendif;? >",$this->template); }else{ exit('错误: 语法错误,没有封闭IF条件语句'); } } returntrue; } privatefunction_parse_common(){ $patten="/\{#\}([^{]*)\{#\}/"; if(strpos($this->template,'{#}')! ==false){ $this->template=preg_replace($patten," php/*$1*/? >",$this->template); } returntrue; } privatefunction_parse_foreach(){ if(preg_match("/\{\s*\\$[0-9a-zA-Z_]+\s*->\s*foreach/",$this->template)){ if(preg_match("/{\s*\/foreach\s*}/",$this->template)){ if(preg_match("/\{\s*@[0-9a-zA-Z_]+/",$this->template)){ $k_and_v_patten="/\{\s*@([0-9a-zA-Z_]+)\s*\}/"; $this->template=preg_replace($k_and_v_patten," phpecho\$$1;? >
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编写 模板 类三步曲