Focus on WEB Application and Software Engineering
三月 03
总体来说,模板引擎是一个"好东西"

作为一个PHP/Perl的程序员,许多模板引擎(fastTemplate, Smarty, Perl的 HTML::Template)的用户,以及我自己的(bTemplate [1] 的作者),我讲这句话很多次了。

然而,在同事进行了长时间的讨论之后,我确信了大量的模板引擎(包括我自己写的)根本是错误的。 我想唯一的例外是Smarty [2],虽然我认为它太庞大了,并且考虑到这篇文章的其余部分相当的没有观点。然而,就你为什么选择Smarty(或者类似的解决方案)有几个理由,这些将在文章后面探究。

这篇文章讨论模板的理论。我们将看到为什么大部分"模板引擎"是过于肥大,并且最终我们将回过头来看一个轻量级的,小巧快速的另类选择。


下载和授权
模板类和所有在本文中使用的例子能够在这里下载:template.zip[3]。你可以根据发布 [4]在 OSI [5] 的 MIT Open Source License使用这些文件中的代码。 

一些关于模板引擎的背景知识
让我们首先研究一下模板引擎的背景知识。模板引擎被设计出来用于把商业逻辑(例如从数据库中获取数据或者计算贸易耗费)从数据的表现分离开来。模板引擎解决了两个主要问题:


如何实现这种分离 
如何从HTML中分离"复杂"的php代码 

这从理论上使得没有PHP经验的HTML设计者能够不看任何PHP代码的条件下修改站点的外观。

然而,模板系统也引入了一些复杂性。首先,我们现在有一个从多个文件得来的"页面"。典型的,你可能有一个主PHP页负责业务逻辑,一个外面的"布局"模板把整个站点的整体布局进行渲染,一个内部的内容特定的模板,一个数据库抽象层,以及模板引擎本身(这些可能是也可能不是由多个文件组成)。也有可能,一些人仅仅简单地在每个PHP页面的首尾处包含"头部"和"尾部"文件。

这产生的单个页面的文件数量是很可观的。然而,因为PHP解析器非常快,用到的文件数量可能不是那么重要除非你的站点流量很大。
然而,要记住模板系统引入了另外一个处理的层次。模板文件不仅仅是必须被包含,他们还必须被解析(取决于模板系统,这个行为有很多种方式来完成 —— 使用正则表达式,字符串替换,编译,词法分析,等等)。这就是为什么对模板进行测速变得流行起来:因为模板引擎使用各种方法来解析数据,它们中的一些比另外一些要快(而且,一些模板引擎提供了比其他引擎更加丰富的功能)。

模板引擎基础知识
简单地说,模板引擎利用了用C写的脚本语言(PHP)。在这些嵌入的脚本语言中,你有另外一个伪脚本语言(无论你的模板引擎支持何种标签)。某些提供了简单的变量改写和循环。另外一些呢,则提供了条件和嵌套循环。而再其他的呢(至少有Smarty)提供了一个PHP的比较大的子集的接口,以及一个缓冲层。

为什么我认为Smarty最接近于正确的方向?因为Smarty的目标是"把业务逻辑从表现中分离出来"而不是"PHP代码和HTML代码的分离"。这看上去区别不大,但是它正是要点所在。任何模板引擎的最终目标不应该是从HTML移除所有的逻辑。它应该是把表现逻辑从业务逻辑中分离出来。

有很多你仅仅需要逻辑来正确显示你的数据的例子。例如,你的业务逻辑是从你的数据库中获取一个用户列表。你的表现逻辑可能是把用户列表用3列显示。可能修改用户列表函数使得它返回3个数组是很笨的办法。毕竟函数不应该关心数据接下来要怎么处理这样的事情。然而,在你的模板文件中缺少一些逻辑,那些正是你要做的事情。

在这点上Smarty是正确的(使得你利用PHP的很多东西),但是仍然有许多问题。基本上,它仅仅提供了一个以新语法访问PHP的接口。以那开始,它看上去不那么聪明了。是不是事实上写 {foreach --args} 比 <? foreach --args ?> 更加简单?如果你认为这样简单一些,问问你自己是不是在包含一个巨大的模板库来到成这种分离时能够看到真正的意义要更加简单一些。诚然,Smarty提供了许多其他很好的特性,但是看上去这些益处能够在不用承担包含Smarty类库的情况下也能获得。

别样的解决方案
我主要要鼓吹的一个解决方案是一个使用PHP代码作为它的原生脚本语言的"模板引擎"。我知道这以前有人做过。而且当我第一次看到的时候,我想,"为什么要这样做?",然而我在考虑过我同事的论据之后,并且实现了一个直接使用PHP代码仍然实现了把业务逻辑和表现逻辑分离的最终目标的模板系统时(只用了大约25行代码,不包括注释),我意识到了好处所在。

这个系统给像我们这样的开发者提供了对PHP核心函数的访问权利,我们能够使用他们来格式化输出——像日期格式化这样的任务应该在模板中处理。而且,因为模板是普通的PHP文件,像Zend Performance Suite [6] 和PHP Accelerator [7] 这样的字节码缓存程序,能够自动缓存模板(因而,它们不需要在每次被访问时都被重新解释执行)。只要你记得把你的模板文件命名为程序能够辨认出是PHP文件的名字(通常,你仅仅需要确保它们有一个.php的后缀),这确实是一个好处。

当我认为这种方法比经典的模板引擎要高明得多时,肯定还有一些要商榷的问题。最明显的反面意见是,PHP代码太复杂了,而且设计者不应该强迫去学习PHP。事实上,PHP代码和像Smarty这样的高级模板引擎的语法差不多简单(如果不是更简单的话)。而且,设计者能够使用像<?=$var;?>这样的简写PHP。这要比{$var}复杂很多?当然,这要长一些,但是如果你习惯了,你能够获得了PHP的威力而且不用承受解析模板文件带来的负担。 
第二,而且可能更重要的,在基于PHP的模板中没有固有的安全。Smarty提供了选项在模板文件中彻底禁用PHP代码。它使得开发者能够约束模板能够访问的函数和变量。如果你没有不怀好意的设计者,这不会是什么问题。然而,如果你允许外部的用户上传或者修改模板,我在此展示的基于PHP的解决方案绝对没有任何安全可言!任何代码都能放入模板中并且得到运行。是的,甚至是一个print_r($GLOBALS)(这将改有恶意的用户访问脚本中任何变量的权利)。

但是,我个人或者工作上写过的项目中,绝大多数不允许最终的用户修改或者上传模板。如果是这样,问题就不存在了。因此现在让我们来看看代码吧。

例子
这是一个简单的用户列表页面的例子。
http://www.chinahtml.com/programming/2/2006/php-11403163643604.shtml

[1] http://www.massassi.com/bTemplate/
[2] http://smarty.php.net/
[3] http://www.sitepoint.com/examples/tempeng/template.zip
[4] http://opensource.org/licenses/mit-license.html
[5] http://www.opensource.org/
[6] http://zend.com/store/products/zend-performance-suite.php
[7] http://www.php-accelerator.co.uk/
[8] http://www.php.net/manual/en/control-structures.alternative-syntax.php
[9] http://wact.sourceforge.net/index.php/TemplateView
[10] http://www.phppatterns.com/index.php/article/articleview/11/
[11] http://simplet.sourceforge.net/
[12] http://phppatterns.com/index.php/article/articleview/4/1/1/
[13] http://smarty.php.net/


本文英文原版地址:http://www.sitepoint.com/article/1218/

当前评分 2.1 , 共有 90 人参与

  • Currently 2.133334/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

添加评论


 

看不清?点击图片看看
biuquote
Loading



关于我

kittow (天笑)
80年代生于“天府之国”四川
爱好:编程、篮球、数码、旅游
乘一叶兴趣小舟,漂泊于浩瀚IT海洋。。。
TITLE:MSE of UESTC & 软件设计师
Technical Capacity | Last Blog