smarty3 include file中使用block产生的bug及解决方式

问题
smarty3的一个很重要,也是很方便的特性是模板继承。今天碰到了一个模板继承相关的题,记录一下。

原码有点多,所以将问题代码抽象如下:
tpl.parent.htm:

{block name="body"} 
parent body 
{/block} 
{include file="tpl.parentFooter.htm"}

tpl.parentFooter.htm:

{block name="footer"} 
parent footer 
{/block} 

tpl.child1.htm
{extends file="admin/tpl.parent.htm"} 
{block name="body"} 
child1 body 
{/block} 
{block name="footer"} 
child1 footer 
{/block} 

tpl.child2.htm
{extends file="admin/tpl.parent.htm"} 
{block name="body"} 
child2 body 
{/block} 
{block name="footer"} 
child2 footer 
{/block} 

渲染tpl.child1.htm,我们得到页面
child1 body child1 footer  
接着渲染tpl.child2.htm。我们预期的结果是:
child2 body child2 footer   

但实际的结果令人沮丧,我们看到的是:
child2 body child1 footer 

清理c_template目录中的模板编译文件。调换一下渲染顺序(先tpl.child2.htm,再tpl.child1.htm),得到的结果分别是:
child2 body child2 footer  
child1 body child2 footer 

what's wrong! 是伟大的继承机制有bug,还是我们做错了什么?

 

解决
几经实验,发现将tpl.parentFooter.htm的代码直接写入tpl.parent.htm,而不是用include的方式引入,渲染模板的结果和我们的预期是一致的。当然,如果情况所需,必须要使用include也是有办法的,那就是使用inline参数。
将tpl.parent.htm的最后一行改为:

{include file="tpl.parentFooter.htm" inline}
问题也可得以解决。

试着分析下原因
对于编译好的模板文件,smarty不会重新处理其block部分,而只是对模板中的assign的变量做替换。除非有某种条件可以让模板文件被重新编译,比如模板自身有了修改或者编译好的模板文件被删除。

对应我们的例子,由于tpl.parentFooter.htm被两个模板共用,自然哪个模板先被渲染,其block部分就先被写进tpl.parentFooter.htm的编译文件。二次渲染时,tpl.parentFooter.htm的编译文件内容被未改变,自然得到的只能是之前的内容。

再看代码,在先渲染tpl.child1.htm时,tpl.parentFooter.htm对应的编译文件
4f8eb313212228edb2051b2212bfffc596075d43.file.tpl.parentFooter.htm.php
最后几行为block相应的代码

<?php if ($_valid && !is_callable('content_5321c3377c1fc9_56610175')) {function content_5321c3377c1fc9_56610175($_smarty_tpl) {?>
child1 footer
<?php }} ?>

我们将其含意理解为,如果使用block,相应内容为child1 footer。

在渲染tpl.child2.htm时,由于tpl.parentFooter.htm对应的编译文件已生成,不会重新编译,自然就只能得到child1 footer的内容了。

 

 

 

你可能感兴趣的:(bug,Smarty3,模板继承)