套模版的时候最烦的就是重复内容了,虽然ecshop cls_template.php支持{include file=”}, 但是有些时候还是麻烦了点, 所以就打算在此扩展一下 增加模版继承的支持。
下面是实现代码
这里只是简单实现了{extend}{block}标签 ,支持多重继承。
/*
* 把结果中的 block标签过滤掉,只要里面的内容
*/
function trim_block($source){
return preg_replace('/{block name=[^}]*}(.*){\\/block}/Us', '\1', $source);
}
function extend_file($source){
global $files;
$p="/{extends file='(.*)'}/";
$count=preg_match_all($p,$source,$out);
if($count==0){
return $source;
}
#print_r($out);
$filename=$out[1][0];//获取继承的模版路径路径
$p_contents=extend_file($files[$filename]);
return extend_block($source,$p_contents);
}
/**
* 继承模版内容
* @param $s_contents 子模板中的内容
* @param $p_contents 父模板中的内容
* return string 继承后的模版内容
*/
function extend_block($s_contents,$p_contents){
$pblock=get_block($p_contents);
$sblock=get_block($s_contents);
foreach($pblock as $key=>$v){
if(isset($sblock[$key])){
$p_contents=str_replace($v['b'],$sblock[$key]['b'],$p_contents);
}
}
return $p_contents;
}
/**
* 提取模版中的block标签信息 返回一个数组
* @param $str 模版内容
* return array
返回格式如下(简化了表示一下为json格式):
{ "title" :{"val":"默认页面标题","b":"{block name='title'}默认页面标题{/block}"},
"head" :{"val":"head 内容","b" : "{block name='head'}head 内容{/block}"}
}
*/
function get_block($str){
$pattern ="/{block name=['|\"](\w*)['|\"]}(.*){\\/block}/Us";
preg_match_all($pattern ,$str,$matches ,PREG_SET_ORDER);
$l=array();
foreach($matches as $v){
$l[$v[1]]=array('val'=>$v[2],'b'=>$v[0]);
}
#print_r($l);
return $l;
}
下面是测试代码
//此处为了简化代码将文件内容放到了数组中
$files['test1.html']="
<html>
<head>
<title>{block name='title'}默认页面标题{/block}</title>
{block name='head'}{/block}
</head>
<body>
{block name='body'}{/block}
</body>
</html>
";
$files['test2.html']="
{extends file='test1.html'}
{block name='head'}
<!--子模版中的head覆盖了test1的title 但是也会被下面test3覆盖掉-->
<link href=\"/css/style.css\" type=\"text/css\"/>
{/block}
";
$files['test3']="
{extends file='test2.html'}
{block name='title'}我的页面标题 我把test1 中的title覆盖了{/block}
{block name='head'}
<link href=\"/css/style.css\" type=\"text/css\"/>
<script src=\"/js/common.js\"></script>
{/block}
{block name=\"body\"}我的HTML页面内容在这里{/block}
";
echo "result:\n";
print $out=extend_file($files['test3']);
echo "最终结果:\n";
print trim_block($out);
输出结果
result:
<html>
<head>
<title>{block name='title'}我的页面标题 我把test1 中的title覆盖了{/block}</title>
{block name='head'}
<link href="/css/style.css" type="text/css"/>
<script src="/js/common.js"></script>
{/block}
</head>
<body>
{block name="body"}我的HTML页面内容在这里{/block}
</body>
</html>
最终结果:
<html>
<head>
<title>我的页面标题 我把test1 中的title覆盖了</title>
<link href="/css/style.css" type="text/css"/>
<script src="/js/common.js"></script>
</head>
<body>
我的HTML页面内容在这里
</body>
</html>
参考