Smarty模板的编译和缓存机制

风行水上 @ 2011-12-18 23:39:17
标签:

Smarty是一个PHP的模板引擎。

Smarty的核心实际上是一个编译器。这个编译器需要解决两个问题:

  1. 把Smarty模板编译为PHP代码形式的模板 (Compiled Template)
  2. 把Compiled Template编译为PHP代码形式的缓存文件 (Cached Page)

下面的分析以Smarty 3.0.2版本为基础。

Smarty的Compile机制

Smarty模板的语法解析器(parser)对应的Php文件为smarty_internal_templateparser.php

在解析到Smarty标签的时候,会调用相应的class以进行内部状态设置和转换。这些class放在特定命名规则的PHP文件中。

Smarty模板中的标签对应的php文件名以smarty_internal_compile_开头。比如:

对于Smarty自带的标签,以nocache标签为例,相对应的php文件为

  • smarty_internal_compile_nocache.php: Smarty自带的nocache标签
  • smarty_internal_compile_private_registered_block.php: 用户registerPlugin的block类型标签
  • smarty_internal_compile_private_block_plugin.php: 用户扩展的block类型标签

以Smarty自带的nocache标签为例,文件smarty_internal_compile_nocache.php的内容可以概要如下,它定义了两个class以分别对应开始标签和结束标签。

<?php
// 对应开始标签
class Smarty_Internal_Compile_Nocache extends Smarty_Internal_CompileBase {
  public function compile($args, $compiler){
    $this->compiler = $compiler;
        
    $this->compiler->nocache = true;   // 禁止缓存
    $this->compiler->has_code = false; // 标签内容不包含代码
    return true;
  }
}
// 对应结束标签
class Smarty_Internal_Compile_Nocacheclose extends Smarty_Internal_CompileBase {
  public function compile($args, $compiler){
    $this->compiler = $compiler;
    $this->compiler->nocache = false;  // 恢复为允许缓存
    $this->compiler->has_code = false; // 标签内容不包含代码
    return true;
  }
}
?>

如果是用户扩展的标签,虽然实现方法有所不同,但主要目的也是分别针对开始和结束标签作相应的状态设置和代码生成。

Smarty的缓存机制

  • 如果页面不需要缓存,直接运行已经编译成为PHP代码的模板,并输出结果就可以了。
  • 如果整个页面都要缓存,只要把输出结果直接保存起来就可以了。
  • 如果页面需要缓存,但又有部分内容不需要缓存,就不是那么容易了。

Smarty模板需要缓存的对象主要有两种:变量本身和由文本变量等组成的段落区块。

上面的nocache标签的实现代码中提到了两个变量 $compiler->nocache$compiler->has_code

nocache变量用于控制模板解析器的状态以决定是否对模板中的变量进行缓存;has_code则最终决定是否需要对生成的PHP代码作"nocache"处理。nocache是标,has_code是本。nocache作用在模板变量上以决定模板变量的has_code值。

很显然,只有has_code值为false的部分才可以生成缓存,否则则需要动态生成。

对于不能缓存而需要动态生成的部分,Smarty的实现机制可以简单表述如下:

<?
echo $value_cache;
?>

<?
echo '/*%%SmartyNocache:hash_string%%*/',
     '<?php echo $value_nocache;?>',
     '/*/%%SmartyNocache:hash_string%%*/';
 ?>

上面的代码是Compiled Template中PHP代码的样子。第一个echo是需要缓存的变量对应的PHP代码,第二个echo则是不需要缓存的变量对应的PHP代码。

如果页面不需要缓存的情况下,可以通过修改"SmartyNocache"字样所标识部分的代码为直接执行而不是echo,就可以获得最终输出。

如果页面需要缓存,则把Compiled Template的执行输出保存为缓存文件,这时那些不需要缓存的部分实际上变成了PHP代码,这时再次执行缓存文件的输出结果就是最终输出。

Smarty对局部缓存的实现

上面提到Smarty内部是通过变量$nocache来控制是否需要缓存的。如果Smarty模板中的标签包含nocache属性,或者用户通过registerPlugin扩展的plugin指定了nocache属性,Smarty内部都会通过变量$tag_nocache进行记录。并在需要时按照下面的计算更新$nocache的值:

  $nocache = $nocache | $tag_nocache;

这种方式表明,只要一个block被标识为nocache,那它内部所有的内容都会被认为是不能缓存的。这在有些情况下会带来一些不方便。

TODO

标签:

分享到:
comments powered by Disqus

28/31ms