分类目录归档:ecshop

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模板继承

使ecshop 模板中可引用 常量

这篇很早前在博客园写的,现在稍微修改下转过来

据说ecshop的模板类是修改的smarty,不过个人感觉不是修改是完全重写了。它和smarty上只是模板标签上有相同的地方,同时阉割了很多功能。

比如$smarty.const.’常量’,这个就不能用。(其实在模版的有些地方可以直接使用常量,比如在判断语句中,但是你若想输出常量值就不是很方便了)

其实模板引擎原理上并不复杂,只是把一些模板标签替换为php中的函数,变量,语法结构罢了。

这次要在ecshop模板中加入引用常量的功能,只需在函数 cls_template.php中的 make_var()中加入两行代码

 

function make_var($val)
    {
        if (strrpos($val, '.') === false)
        {
            if (isset($this->_var[$val]) && isset($this->_patchstack[$val]))
            {
                $val = $this->_patchstack[$val];
            }
            $p = '$this->_var[\'' . $val . '\']';
        }
        else
        {
            $t = explode('.', $val);
            $_var_name = array_shift($t);
            if (isset($this->_var[$_var_name]) && isset($this->_patchstack[$_var_name]))
            {
                $_var_name = $this->_patchstack[$_var_name];
            }
            if ($_var_name == 'smarty')
            {    
                if($t[0] == 'const'){#此处为新添加
                    return strtoupper($t[1]);
                }
                 $p = $this->_compile_smarty_ref($t);
            }
            else
            {
                $p = '$this->_var[\'' . $_var_name . '\']';
            }
            foreach ($t AS $val)
            {
                $p.= '[\'' . $val . '\']';
            }
        }

        return $p;
    }

其中21-23行是新加的,这让就可在模板文件中通过 {$smarty.const.常量}来引用php中定义的常量了