UCenterHome1.5的模板语法解析 ucenter 1.5.2 下载

原创文章,转载请注明出处http://blog.sina.com.cn/s/blog_65db99840100s4yb.html

=====================================================

在UCH中,模板与动态数据分离,所以在很多php文件的最后,我们会看到包含了模板文件,如cp_blog.php最后有include_once template("cp_blog");

在下面的代码中,命名有规律。$tpl是没有后缀名的,$tplfile是后缀为htm的模板文件,$objfile是后缀为php的缓存文件

UCH里使用模板的流程是:

在php代码中获取动态数据,然后include_once template($tpl)

template函数解析模板文件$tplfile,返回缓存文件$objfile。

template函数中调用parse_template函数解析$tplfile,

$tplfile里有UCH定义的一套语法,在parse_template函数里可以看到,有<!-- templatename--><!—block/name-->等。这些语法在parse_template中都会被替换成对应的函数,如readtemplateblocktags等,这些函数也都位于function_template.php中。

这里有点点纠结的就是,模板文件中可能还通过<!-- templatename-->包含了其他的模板文件,所以在parse_template中要两次调用preg_replace,第一次读模板文件$tplfile所包含的子模板文件name,第二次是读子模板文件name中再包含的孙子模板文件。UCH中至多有3层模板包含关系,即父亲->儿子->孙子,所以不需要第三次调用preg_replace来读取孙子模板文件可能包含的重孙模板文件了。

template函数在function_common.php中定义

function template($name) {

global $_SCONFIG, $_SGLOBAL;

if(strexists($name,'/')) {

$tpl = $name;//$name是完整目录的情况

} else {

$tpl ="template/$_SCONFIG[template]/$name";

$name只是一个文件名的情况,$tpl类似template/default/cp_blog或者template/blue/cp_blog

默认的模板风格是default,但是如果用户选择了其他风格,$_SCONFIG[template]就会变成blue之类的其他值

在首页的右下角可以选择模板风格

}

$objfile =S_ROOT.'./data/tpl_cache/'.str_replace('/','_',$tpl).'.php';

缓存文件名,$objfile类似data/tpl_cache/template_default_cp_blog.php或者data/tpl_cache/template_blue_cp_blog.php

if(!file_exists($objfile)) {

include_once(S_ROOT.'./source/function_template.php');

parse_template($tpl);

//如果缓存文件不存在,则对模板文件进行解析

}

return $objfile;

}

parse_template函数在function_template.php中定义

function parse_template($tpl) {

global $_SGLOBAL, $_SC, $_SCONFIG;

//包含模板

$_SGLOBAL['sub_tpls'] = array($tpl);

$tplfile = S_ROOT.'./'.$tpl.'.htm';

$tplfile类似template/default/cp_blog.htm或者template/blue/cp_blog.htm

$objfile =S_ROOT.'./data/tpl_cache/'.str_replace('/','_',$tpl).'.php';

$objfile类似data/tpl_cache/template_default_cp_blog.php或者data/tpl_cache/template_blue_cp_blog.php

//read

if(!file_exists($tplfile)) {

$tplfile =str_replace('/'.$_SCONFIG['template'].'/', '/default/',$tplfile);

//如果非默认模板风格的某个模板文件不存在,那么就改用default风格的该模板文件

}

$template = sreadfile($tplfile);

//读入模板文件内容

if(empty($template)) {

exit("Template file : $tplfile Not found or haveno access!");

}

//模板

$template =preg_replace("/<!--{templates+([a-z0-9_/]+)}-->/ie","readtemplate('\1')", $template);

这就是定义UCH的模板语法了,模板页中的<!--{templatename}-->

被替换成readtemplate(name),readtemplate函数也在function_template.php中定义。name就是([a-zA-Z0-9_/]+)

为什么多了A-Z呢,因为"/<!--{templates+([a-z0-9_/]+)}-->/ie"最后的i选项表示不区分大小写的正则匹配

python里的正则表达式分组,似乎就是用1来表示第一组,这里用了\1

\1为什么又要用单引号裹起来呢,这是因为readtemplate函数的参数要是一个字符串

//处理子页面中的代码

$template =preg_replace("/<!--{templates+([a-z0-9_/]+)}-->/ie","readtemplate('\1')", $template);

//解析模块调用

$template =preg_replace("/<!--{block/(.+?)}-->/ie","blocktags('\1')", $template);

<!--{block/name}-->被替换成blocktags(name)

name就是(.+?).匹配除换行符外的任意字符,+表示出现一次或多次

?表示懒惰匹配,不然后面的}->都会被.+匹配掉

//解析广告

$template =preg_replace("/<!--{ad/(.+?)}-->/ie","adtags('\1')", $template);

<!--{ad/name}-->被替换成<!--adtags(name)-->

如space_doing.htm里有一个<!--{ad/header}-->被替换成了<!--AD_TAG_1-->

//时间处理

$template =preg_replace("/<!--{date((.+?))}-->/ie","datetags('\1')", $template);

<!--{date(name)}-->被替换成datetags(name)

如space_doing.htm里有一个

<!--{date('m-dH:i',$basevalue[dateline],1)}-->被替换成了<!--DATE_TAG_7-->

//头像处理

$template =preg_replace("/<!--{avatar((.+?))}-->/ie","avatartags('\1')", $template);

<!--{avatar(name)}-->被替换成avatartags(name)

如space_doing.htm里有一个<!--{avatar($_SGLOBAL[supe_uid],small)}-->被替换成了<!--AVATAR_TAG_10-->

//PHP代码

$template =preg_replace("/<!--{evals+(.+?)s*}-->/ies","evaltags('\1')", $template);

<!--{evalphp_expression}-->被替换成evaltags(php_expression)

php_expression就是(.+?)而且这里的.匹配包括换行符在内的一切字符这是由/ies中的s选项确定的

如space_doing.htm里有一个<!--{eval echoformhash();}-->被替换成了<!--EVAL_TAG_16-->

//开始处理

//变量

$var_regexp ="((\$[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*)([[a-zA-Z0-9_-."'[]$x7f-xff]+])*)";

一开始为什么要用三个,我搞不明白。试验了一下,\$匹配的就是$,而改成$却没能匹配模板文件里的变量名。这个我还没搞明白。

$var_regexp匹配变量名

[a-zA-Z_x7f-xff]变量名以字母或下划线或汉字开头

x7f-xff这个让人非常困惑,到底是想匹配什么呢?难道是想匹配扩展ASCII码吗?0x7f-0xff确实是扩展ASCII码表的范围,但显然没人会用这些控制字符去当变量名。

我这个UCH是UTF-8版本的,从UCS-2(就是现在通用的Unicode)到UTF-8的编码方式如下:

UCS-2编码(16进制)

UTF-8字节流(二进制)

0000 -007F

0xxxxxxx

0080 -07FF

110xxxxx10xxxxxx

0800 -FFFF

1110xxxx10xxxxxx 10xxxxxx

前面的0000-007F是兼容ASCII码的

汉字的unicode编码在0080-FFFF里,转换成UTF-8后的字节是

110xxxxx或10xxxxxx或1110xxxx,在0x01111111-0x11111111范围内,也即0x7f-0xff。

更精确地,这个匹配变量名开头的部分可以写成[a-zA-Z_xc0-xef],因为汉字的开始字节只可能是110xxxxx或1110xxxx,范围就是0xc0-0xdf和0xe0-0xef

[a-zA-Z0-9_x7f-xff]*比变量名的开头字节的允许取值范围多了数字,和C语言是一样的,变量名不能以数字开头

更精确地,这里可以写成[a-zA-Z0-9_x80-xef]*因为这里汉字的字节可能是110xxxxx或1110xxxx或10xxxxxx,比0xc0-0xef多了10xxxxxx,即0x80-0xbf,合起来就是0x80-0xef

([[a-zA-Z0-9_-."'[]$x7f-xff]+])*

变量可能是数组形式的,如$name1[$name2],$[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*匹配了$name1,后面的[$name2]怎么匹配呢?我一开始以为是[$[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]],因为[]里面也应该是一个变量名。

但是变量可能是嵌套数组形式的,如$name1[$name2[$name3[$name4]]],此时用$[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]来一个个匹配变量名明显不可行。所以只是用[]把可能的字符都框起来,希望程序员不要写太扯淡的变量名了。

$template =preg_replace("/<!--{(.+?)}-->/s","{\1}",$template);

形如<!--{name}-->的字符串被替换成{name}

前面解析广告,时间处理等产生的<!--EVAL_TAG_15-->等都不匹配,仍然保留

name就是(.+?)这里的.匹配包括换行符在内的所有字符(有/s选项)?表示懒惰匹配

$template = preg_replace("/([nr]+)t+/s","\1",$template);

去掉换行回车后的制表符

$template =preg_replace("/(\$[a-zA-Z0-9_[] '"$x7f-xff]+).([a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*)/s","\1['\2']",$template);

形如$name1.name2替换成$name1[name2],不要搞成了$name1['name2'],'\2'和"\1"都是正则表达式的后向引用。可是我在模板文件中还没找到例子

$template =preg_replace("/{(\$[a-zA-Z0-9_[]'"$.x7f-xff]+)}/s","<?=\1?>", $template);

形如{$name1}替换成<?=$name1?>

如space_doing.htm里有{$_SN[$space[uid]]}被换成了

<?=$_SN[$space[uid]]?>

$template = preg_replace("/$var_regexp/es","addquote('<?=\1?>')",$template);

将没有被{}包裹的变量名替换成addquote('<?=\1?>')

addquote的作用是将类似[name]转换成[‘name’]

如space_doing.htm里有{if $space}被替换成了{if<?=$space?>}

但是这样也有副作用,比如space_doing.htm里有{$_SN[$space[uid]]},在上一条语句中被替换成了<?=$_SN[$space[uid]]?>,在这又被替换成了<?=<?=$_SN[$space['uid']]?>?>

$template =preg_replace("/<?=<?=$var_regexp?>?>/es","addquote('<?=\1?>')",$template);

消除上一条语句的副作用,将<?=<?=$_SN[$space['uid']]?>?>换成<?=$_SN[$space['uid']]?>

//逻辑

$template =preg_replace("/{elseifs+(.+?)}/ies","stripvtags('<?php } elseif(\1) {?>','')", $template);

{elseifexpression1}替换成stripvtags('<?php } elseif(expression1) {?>','')

stripvtags的作用是将类似<?=$name?>替换成$name

$template = preg_replace("/{else}/is","<?php } else { ?>",$template);

{else}替换成<?php } else {?>

//循环

for($i = 0; $i < 5; $i++){

$template =preg_replace("/{loops+(S+)s+(S+)}(.+?){/loop}/ies","stripvtags('<?php if(is_array(\1)) { foreach(\1as \2) {?>','\3<?php} }?>')", $template);

解析loop

UCenterHome1.5的模板语法解析 ucenter 1.5.2 下载

将类似{loop array1 key1} expression1{/loop}替换成

stripvtags(

<’?php if(is_array(array1)) {foreach(array1 as key1){?>’,

‘expression1<?php } }?>’

如space_doing.htm里将

<title>{if<?=$_TPL['titles']?>}{loop<?=$_TPL['titles']?><?=$value?>}{if<?=$value?>}<?=$value?>- {/if}{/loop}{/if}{if<?=$space?>}<?=$_SN[$space['uid']]?>-{/if}<?=$_SCONFIG['sitename']?>

替换成了

<title>{if<?=$_TPL['titles']?>}<?php if(is_array($_TPL['titles'])){ foreach($_TPL['titles'] as $value) {?>{if<?=$value?>}<?=$value?>- {/if}<?php } }?>{/if}{if<?=$space?>}<?=$_SN[$space['uid']]?>-{/if}<?=$_SCONFIG['sitename']?>

$template =preg_replace("/{loops+(S+)s+(S+)s+(S+)}(.+?){/loop}/ies","stripvtags('<?php if(is_array(\1)) { foreach(\1as \2 =>\3){ ?>','\4<?php} }?>')", $template);

解析loop

将类似{loop array1 key1 value1} expression1{/loop}替换成

stripvtags(

<’?php if(is_array(array1)) {foreach(array1 askey1=>value1){?>’,

‘expression1<?php } }?>’

如space_doing.htm里将

{loop<?=$moodlist?><?=$key?><?=$value?>}

<li>

<div><ahref="space.php?uid=<?=$value['uid']?>&do=doing"><imgsrc="<!--AVATAR_TAG_14-->"alt="<?=$_SN[$value['uid']]?>"/></a></div>

<p><ahref="space.php?uid=<?=$value['uid']?>"title="<?=$_SN[$value['uid']]?>"><?=$_SN[$value['uid']]?></a></p>

<p><!--DATE_TAG_9--></p>

</li>

{/loop}

替换成了

<?php if(is_array($moodlist)) {foreach($moodlist as $key => $value) {?>

<li>

<div><ahref="space.php?uid=<?=$value['uid']?>&do=doing"><imgsrc="<!--AVATAR_TAG_14-->"alt="<?=$_SN[$value['uid']]?>"/></a></div>

<p><ahref="space.php?uid=<?=$value['uid']?>"title="<?=$_SN[$value['uid']]?>"><?=$_SN[$value['uid']]?></a></p>

<p><!--DATE_TAG_9--></p>

</li>

<?php } }?>

$template =preg_replace("/{ifs+(.+?)}(.+?){/if}/ies","stripvtags('<?php if(\1) {?>','\2<?php}?>')", $template);

解析if

将类似

{if name1}expression1 {/if}

替换成

stripvtags(

<’?php if(name1) {?>’,

‘expression1<?php }?>’

)

如space_doing.htm里将

{ifempty(<?=$_SGLOBAL['inajax']?>)}

替换成

<?php if(empty($_SGLOBAL['inajax'])) {?>

}

为什么要有for循环呢?因为可能存在循环语句嵌套的情况。

比如space_doing.htm里有这么一段代码

{loop<?=$list?><?=$basevalue?>}

………

………

{loop<?=$clist[$basevalue['doid']]?><?=$value?>}

………

{/loop}

………

{/loop}

$i=0时,

$template =preg_replace("/{loops+(S+)s+(S+)}(.+?){/loop}/ies","stripvtags('<?php if(is_array(\1)) { foreach(\1as \2) {?>','\3<?php} }?>')", $template);

只替换掉了外层的loop,内层的loop被(.+?)所匹配

?表示懒惰匹配,否则后面的{/loop}都会被(.+)所匹配

但是既然是懒惰匹配,为什么(.+?)不是匹配到内层的{/loop}就停止呢?

因为正则表达式有另一条规则,比懒惰/贪婪规则的优先级更高:最先开始的匹配拥有最高的优先权——The match that begins earliestwins。

$i=1时,内层的loop也将被替换掉

从这个for循环我们也可以看出,UCH的模板中最多允许5层嵌套循环,当然这已经足够了

//常量

$template =preg_replace("/{([a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*)}/s","<?=\1?>", $template);

比变量名少了一开始的$,也不考虑数组形式的常量

//替换

if(!empty($_SGLOBAL['block_search'])) {

$template = str_replace($_SGLOBAL['block_search'],$_SGLOBAL['block_replace'], $template);

}

//换行

$template = preg_replace("/?>[nr]*<? /s", " ",$template);

?>

<?

前一段php代码的结尾和下一段php代码的开始都被以空格代替了

//附加处理

$template = "<?phpif(!defined('IN_UCHOME')) exit('AccessDenied');?><?phpsubtplcheck('".implode('|', $_SGLOBAL['sub_tpls'])."','$_SGLOBAL[timestamp]','$tpl');?>$template<?phpob_out();?>";

//write

if(!swritefile($objfile, $template)) {

exit("File: $objfile can not bewrite!");

}

写入缓存文件

所以在template函数最后,无论$objfile一开始是否存在,最后都是返回$objfile

}

function readtemplate($name){

global $_SGLOBAL, $_SCONFIG;

$tpl =strexists($name,'/')?$name:"template/$_SCONFIG[template]/$name";

$tplfile = S_ROOT.'./'.$tpl.'.htm';

$_SGLOBAL['sub_tpls'][] = $tpl;

if(!file_exists($tplfile)) {

$tplfile =str_replace('/'.$_SCONFIG['template'].'/', '/default/',$tplfile);

}

如果$_SCONFIG['template']风格的模板文件不存在,则改用default风格的模板文件

$content = sreadfile($tplfile);

//读入模板文件的内容

return $content;

}

function addquote($var) {

return str_replace("\"", """,preg_replace("/[([a-zA-Z0-9_-.x7f-xff]+)]/s", "['\1']",$var));

这个preg_replace感觉没什么用啊,[name1]替换成[name1]?

str_replace将\"替换成"

}

function blocktags($parameter){

global $_SGLOBAL;

$_SGLOBAL['i']++;

$search ="<!--BLOCK_TAG_{$_SGLOBAL['i']}-->";

按广告出现的次序,依次将{block/name}替换成BLOCK_TAG_1 BLOCK_TAG_2等等

$_SGLOBAL['block_search'][$_SGLOBAL['i']] =$search;

$_SGLOBAL['block_replace'][$_SGLOBAL['i']] ="<?php block("$parameter");?>";

return $search;

}

function adtags($pagetype) {

global $_SGLOBAL;

$_SGLOBAL['i']++;

$search ="<!--AD_TAG_{$_SGLOBAL['i']}-->";

按广告出现的次序,依次将{ad/name}替换成AD_TAG_3 AD_TAG_4等等

这个编号是跟着前面的BLOCK_TAG来的

$_SGLOBAL['block_search'][$_SGLOBAL['i']] =$search;

$_SGLOBAL['block_replace'][$_SGLOBAL['i']] ="<?php adshow('$pagetype');?>";

return $search;

}

function datetags($parameter) {

global $_SGLOBAL;

$_SGLOBAL['i']++;

$search ="<!--DATE_TAG_{$_SGLOBAL['i']}-->";

按date模板方法出现的次序,依次将{date(name)}替换成DATE_TAG_7 DATE_TAG_8等等

注意这里的编号是跟着前面的AD_TAG来的

$_SGLOBAL['block_search'][$_SGLOBAL['i']] =$search;

$_SGLOBAL['block_replace'][$_SGLOBAL['i']] ="<?php echo sgmdate($parameter);?>";

return $search;

}

function avatartags($parameter) {

global $_SGLOBAL;

$_SGLOBAL['i']++;

$search ="<!--AVATAR_TAG_{$_SGLOBAL['i']}-->";

按avatar模板方法出现的次序,依次将{avatar(name)}替换成AVATAR_TAG_9 AVATAR_TAG_10等等

注意这里的编号是跟着前面的DATE_TAG来的

$_SGLOBAL['block_search'][$_SGLOBAL['i']] =$search;

$_SGLOBAL['block_replace'][$_SGLOBAL['i']] ="<?php echo avatar($parameter);?>";

return $search;

}

function evaltags($php) {

global $_SGLOBAL;

$_SGLOBAL['i']++;

$search ="<!--EVAL_TAG_{$_SGLOBAL['i']}-->";

按eval模板方法出现的次序,依次将{eval php_expression}替换成EVAL_TAG_16 EVAL_TAG_17等等

注意这里的编号是跟着前面的AVATAR_TAG来的

$_SGLOBAL['block_search'][$_SGLOBAL['i']] =$search;

$_SGLOBAL['block_replace'][$_SGLOBAL['i']] ="<?php ".stripvtags($php)."?>";

return $search;

}

function addquote($var) {

returnstr_replace("\"", """,preg_replace("/[([a-zA-Z0-9_-.x7f-xff]+)]/s", "['\1']",$var));

preg_replace将类似[name]转换成[‘name’]

str_replace将\转换成不过我还没找到例子

}

function stripvtags($expr, $statement=''){

$expr= str_replace("\"", """,preg_replace("/<?=(\$.+?)?>/s","\1", $expr));

preg_replace将<?=$name?>替换成$name

$statement= str_replace("\"", """, $statement);

return$expr.$statement;

}

  

爱华网本文地址 » http://www.aihuau.com/a/25101014/227615.html

更多阅读

笔记本改触摸屏最好的方法,只需要1分钟! 笔记本触摸屏驱动

笔记本改触摸屏最好的方法,只需要1分钟!——简介 现在手机是可以触摸的,平板电脑是可以触摸的,新出的笔记本也是触摸的,那么以前的笔记本电脑没有触摸怎么办,我们如果把它束之高阁,又于心不忍,那怎么办,现在新出了一款外置的笔记本触摸屏,只需

怎样区别第1、2、3代水床? i5 2代和3代的区别

怎样区别第1、2、3代水床?主要是从水床内胎材质上进行区别,第一代水床内胎是以棉布经橡胶硫化处理后制成的。其优点是原材料成本低,生产设备少,生产工艺简单,缺点是:1.只能用它制“地垄沟”全水结

如何修改新浪微博的模板/背景图片 新浪微博怎么修改背景

一直在玩魔兽,今天突然想把微博的模板改成魔兽喜欢的图片。研究了一上午,在这里把心得体会写上,希望能帮助大家。 首先点击模板界面如图 选择“自定义”点击浏览插入你想要的图片这里先说只放一张图片怎么操作你可以选择“平铺”

声明:《UCenterHome1.5的模板语法解析 ucenter 1.5.2 下载》为网友梦里面的仙人掌分享!如侵犯到您的合法权益请联系我们删除