php模版引擎 模版继承{extends}的简单实现

套模版的时候最烦的就是重复内容了,虽然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>

参考

smarty模板继承

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注