02月11, 2010

Smarty中实现模板继承功能

在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模板引擎。

本文链接:http://welefen.com/post/smarty-tpl-inherit.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。