模板引擎SMARTY

网络整理 - 07-27
用PHP实现MVC开发模式的逻辑层和表示层有多种模板引擎可供选择,但是官方引擎SMARTY诞生后,选择就有了变化。它的理念和实现都是相当"前卫"的。本文主要讨论SMARTY之于其他模板引擎的不同特点,简要介绍了该引擎的安装及使用,并用一个小的测试案例对比了SMARTY和PHPLIB template的速度和易用性。

点击查看原图

该图展示了一个简单的WEB应用程序,用户在浏览器上看到信息是数据库服务器上的内容,但在这之前经过了应用服务器加工。开发人员负责的就是建立数据结构、处理数据的逻辑以及表示数据的方法。

96年CGI在中国开始流行的时候,早期的WEB程序员都是从HTML开始自学成材的,在PERL中print一行行的HTML并不是一件难事,但是随着网络的一步步提速,页面大小也从当初的二、三十K暴涨了十倍。写CGI程序就产生了一个迫切的要求:分开PERL和HTML源码。于是,社会进步体现在开发小组内部的分工上。由于美工和程序员对互相的工作并不是十分熟悉,在进行合作的过程中需要用一种约定的"语言"进行交流。

这种语言并不是我们的母语或者英语,术语叫做"模板",逻辑和表示依靠它联系。它是结合了HTML和脚本语言特征的一种表达方式。通过这种方式,表示层可以按照用户所希望的格式来显示经过逻辑层处理过的数据。如果你有Windows平台下MFC的开发经验,那么一定会很熟悉Document/Document Template/View的封装,这就是一个很典型的MVC例子。对于Web应用来说,个人认为J2EE中的EJB/servlets/JSP是最强大的,当然还有简洁优美的Structs。另一个很有名的实现就是COM/DCOM+ASP,这个组合在我国是最多人使用的。

通过几种MVC实现在WEB应用程序里的对比,可以得到一个关于模板的概念:一组插入了HTML的脚本或者说是插入了脚本HTML,通过这种插入的内容来表示变化的数据。下面给出一个模板文件的例子,这个模板经过处理后在浏览器里显示"Hello, world!"

<html> <head> <title>$greetings</title> </head> <body> $greetings <body></html>

这里暂且省略处理方式,在后面做专门对比讨论。

点击查看原图

就需要在index.php里指定目录结构:

$smart->template_dir = "smarty/templates/";$smart->compile_dir = "smarty/templates_c/";$smart->config_dir = "smarty/configs/";$smart->cache_dir = "smarty/cache/";

第一个问题解决了,紧接着就是第二个:我刚用Dreamweaver生成的漂亮模板怎么不能用?并不是模板文件有什么问题,而是因为SMARTY默认的标记分隔符是{},不巧的是Javascript肯定包含这个标记。好在我们可以用任意字符当作分隔符,再加上这两句:

$smart->left_delimiter = "{/";$smart->right_delimiter = "/}";

这下安装就基本完成,没问题了。

点击查看原图

下面就深入到测试中来。先看看两种模板文件的语法:蓝条左边是PHPLIB template的模板,右边属于SMARTY。个人偏好是不一样的,所以这里不作评论。着重对比一下脚本里的处理语句,先看PHPLIB template的:

$tpl->set_file('phplib', 'bigfile.htm');$tpl->set_block('phplib', 'row', 'rows');for ($j = 0; $j < 10; $j++){ $tpl->set_var('tag' ,"$j"); $tpl->parse('rows', 'row', true);}$tpl->parse('out', 'phplib');$tpl->p('out');

下面是SMARTY的:

$smart->assign('row',$row);$smart->display('bigfile.htm');

SMARTY只用了tags和row两个变量,而PHPLIB template则多了模板文件的handler,还有一个莫名其妙的out。说实在的这个out我当初学的时候就不知道为什么要存在,现在看起来,还是别扭。为什么SMARTY少那么多处理语句呢?答案是工作由引擎完成了。如果你喜欢钻研源程序,可以发现在Smarty_compiler.class.php里有一个名叫_compile_tag()的函数,由它负责把section这个标签转换成php语句。这不是一个普通的标签,它带有参数和数据,节省了脚本编程的工作量,而模板标签上的工作量相差又不大,可以判定在易用性上SMARTY高出一畴。

下面该轮到我们最关注的速度了,毕竟对于一个熟练的web开发者来说,掌握再困难的工具不过是时间问题,何况模板引擎这种学习曲线平缓的技术。而速度则是web应用程序的生命,尤其是模板引擎使用在并发访问量很大的站点上,这点就更重要了。测试开始前,我觉得PHPLIB template会在这一环节上胜出,因为它经历了很多次升级,已经基本没有什么bug,而且SMARTY的引擎个头太大,不像它的对手只有两个文件。

果然,测试结果如下图,PHPLIB template有25%的速度优势:

点击查看原图

但不会一直这样,我又按了一次刷新,这次得到了不一样的结果:

点击查看原图

PHPLIB基本没变化,但是SMARTY提高了25%的速度。继续刷新,得到的都是类似于第二次的结果:SMARTY比PHPLIB template 快上近10%。我想这就是编译型比解释型快的原理了。SMARTY引擎本身就很大,加上还要把模板编译成php文件,速度当然比不上小巧的PHPLIB template。但这只是第一次的情况。第二次接到请求的时候,SMARTY发现该模板已经被编译过了,于是最耗时的一步被跳过了,而对手还要按部就班地进行查找和替换工作。这是编译原理里讲到的很经典的"用空间换时间"例子。

五、结论
结论就是如果你已经爱上SMARTY了,那么还等什么呢?当然并不是说它就全能,就如同我用MVC模式来写我的个人网站,非但没有减少工作量,反而总是要为不同层次间的耦合劳神。

SMARTY不适合什么呢?举个手册里的经典例子:天气预报网站。我还想到一个:股市大盘。在这种网站上用SMARTY会由于经常的重编译而效率偏低,还是PHPLIB template更为适合。

本文并不是为了对比两种引擎,而是为了说明SMARTY的优势。使用它最有意义之处在于它是PHP新体系的一部份,作为一支独立的力量,除了.NET和JAVA ONE这两大体系之外,大中型web开发还有别的选择。这对于GNU项目来说,其意义无异于刘邓大军千里跃进大别山。

参考文献

  • SMARTY官方站点:smarty.php.net
  • 王晨:《在PHP世界中选择最合适的模板》
  • 本文中测试程序下载:test.tar.bz2