Smarty中实现模板继承功能

1792次阅读  |  发布于5年以前

在PHP+Smarty大行其道的今天,怎么样进行快速的模板开发成为了前端开发人员必须思考的问题。不同的页面,相同或者相似的页面结构是否进行了模块化处理,同样的头部或者尾部是否进行了内容分离决定了开发的效率。虽然Smarty本身支持include a file的功能,但这远远不够。我们需要的是不想重写同样的页面结构。

Jinja2的模板继承功能

Jinja是基于python的模板引擎,有个非常实用的功能就是模板继承。不太了解的可以去这里看详细的介绍http://opensource.csdn.net/bbs/thread/3943?lp=1

模板继承的好处就是你不在需要写整个页面,只要写页面的模块,然后用一个布局的页面套一下就可以了。并且页面中的模块书写顺序是无序的。

smarty本身并没有模板继承的功能,但我们可以通过block,capture和方法插件(其实block,capture也是插件)。

Smarty实现模板继承

首先我们看看一个实际的页面需要怎么写?

{=block name=page type=normal =} //这里标识block名称和页面类型,这里是{=,=}是smarty的左右标记符,你可以定义其他的

    {=block name=title=}
    这里是页面的标题
    {=/block=}

    {=block name=head_static=}
    这里是页面的静态样式(如css)
    {=/block=}

    {=block name=header=}
    这里是页面的头部
    {=/block=}

    {=block name=content=}
    这里是页面的内容区
    {=/block=}

    {=block name=footer=}
    这里是页面的地步
    {=/block=}

    {=block name=foot_static=}
    这里是页面的静态样式(如js)
    {=/block=}

    {=/block=}

从上面的代码我们可以看到,原本需要写一个完成的页面,现在只需要写页面的模块就可以了。如果某个模块引用是公共模块的话,还可以省略。这里主要的实现方式就是定义了一个为名为block的block块。下面我们看看是怎么解析这些block的。

解析block的插件放在smarty的插件目录下,名为block.block.php文件。

<?php
     function smarty_block_block($params, $content, &$smarty)
    {
    if($content === null) return;
    $name = strtoupper($params['name']);
    //页面型block
    if($name == 'PAGE'){
    $type = $params['type'];
    if(empty($type)){
    $type = 'normal';
    }
    $file = 'inc/page_'. $type . '.html';  //加载页面布局文件
    $output = $smarty->fetch($file); //解析这个页面布局文件
    //通过正则解析
    $pattern = "/".preg_quote ($smarty->left_delimiter).":([a-z_0-9]+):(.*?)".preg_quote ($smarty->right_delimiter)."/is";
    preg_match_all($pattern, $content, $matches);
    $result = array();
    $replace = array();
    for($i=0,$count=count($matches[1]);$i<$count;$i++){
    $item = $matches[1][$i];
    $result[] = $matches[2][$i];
    $replace[] = '/<!--\s*'.$item.'\s*-->/i';
    }
    $output = preg_replace($replace,$result,$output);
    return $output;
    }else{
    //模块型block,如:title,head_static,header,content,footer,foot_static
    return $smarty->left_delimiter.':'.$name.':' . $content .$smarty->right_delimiter;
    }
    }

这个解析文件的原理就是根据block的name和type进行不同的模块解析。如果name为page表示为整个页面,其他值是为页面的子模块。

页面布局文件:

{=include file="inc/inc_base.html"=}

    {=load_css href=base.css =}
    <!-- HEAD_STATIC -->
    <div id="page">
    <div id="header"><!-- HEADER --></div>
    <div id="content"><!-- CONTENT --></div>
    <div id="footer"><!-- FOOTER --></div>
    </div>
    <!-- FOOT_STATIC -->

这个页面首先加载一个公共模板文件,这个文件里定义一些capture,这些capture就是一些公共的内容。页面布局文件定义了页面的布局,加载一些公用的静态文件或者其他模板。

这里整个模板继承功能就实现了。

Smarty实现模板继承的不足

由于smarty解析对这些并没有特殊的优化,所以编译后的文件要加载一些smarty插件文件,这样速度上稍微要差一些,不过差多少要看具体的页面复杂度。

需要做的工作:可以对smarty编译进行优化,使这种实现模式跟原有的在速度上没什么区别。

其他实现方式

1、shell脚本实现。这种方式在速度上跟原有方式没有区别,但每次看效果都要手动编译一次,浪费一些开发时间。

2、大为的lite模板引擎。

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8