[摘要]PHP工程中的模板应用,是进行中型乃至大型项目中建议采用的处理表现层的好办法。但是具体到模板的实施,采用何种现有的模板技术却需要进行一番比较。PHP世界中比较受关注的模板处理有PHPLIB Template和FastTemplate两种,我们对技术的易用性和速度进行了评测--想知道结果吗?事情的起...
PHP工程中的模板应用,是进行中型乃至大型项目中建议采用的处理表现层的好办法。但是具体到模板的实施,采用何种现有的模板技术却需要进行一番比较。
PHP世界中比较受关注的模板处理有PHPLIB Template和FastTemplate两种,我们对技术的易用性和速度进行了评测--想知道结果吗?
事情的起因:你用过FastTemplate吗?
对于PHP工程中的模板应用,其实我和我的同事们已经在许多的项目中接触过--关于它的好处,我想无论是在实际开发阶段还是上升到设计模式的角度都已经有很多"前辈先哲"讨论过了。就项目实施而言,在一些中型甚至大型的项目中,有效的将HTML(还有其他文本形式的表现层)和PHP代码分开,不仅在开发阶段可以分别提高界面设计人员和应用程序编写人员的工作效率,更会给项目的测试和维护带来巨大的便利。
但是--本文的目的不是讨论模板的优缺点,也不是作为指导性的教程讲授如何在PHP项目中使用模板,而是以应用的视角比较两种PHP世界中最为流行的模板处理方式(其实只不过是两种模板类):PHPLIB Template和FastTemplate。
其实我一直都在"安静"的使用着PHPLIB Template--很稳定而且看上去速度也不错,以至于我并不想再去不安的寻找可能更好的替代品--虽然我也知道这个地球上还有FastTemplate这样的东西(而且还在Perl的世界中大名鼎鼎)。直到有一天,有一个同事问我:"不知道FastTemplate怎么样?为什么我们不试试FastTemplate呢?"
"好吧,就让我们试试!"不过作为一个稳妥的方法,在任何新的模式或者方法引入项目之前,最好能够更加全面的了解它,以及找到一个或者几个足够说服自己和同事去采用它的理由--对于FastTemplate也不例外。
主角出场:了解PHPLIB Template以及FastTemplate
前面已经说过,我已经使用PHPLIB有一段时间了--我想屏幕前的你也许和我一样,也对这个优秀的工具类库印象很深吧!同样,当我开始寻求模板的解决办法时,很自然的就会在最接近身边的工具箱里搜寻,于是我找到了PHPLIB中的Template类。在最初的很快浏览完它提供的API之后(当然还得感谢PHPLIB详尽的文档),我就开始了使用它的历程--直到现在。
而FastTemplate似乎名气更响亮一些,在其发迹的Perl世界中自然是这样,在PHP世界中似乎也是,单单从这一点上就足够让人相信它的能力了。
关于两者的使用办法,本来我想在这里多废话几句的;但是毕竟觉得自己恐怕专门写出两篇教程来也没有现有的教程受欢迎--在本文的参考资料中有关于PHPLIB Template和FastTemplate的有名教程,如果你自认还没有对这两种模板或者其中的一种有所认识,建议你先去看看那两篇文章,应该会得到不少有益的模板应用知识。
(一番鼠标点击以及眼球转动甚至亲自编写测试代码之后,)现在你对两种模板都有了一些了解,也许已经发现了它们之间的很多相似之处,在下面我就会将这些地方归纳一下。
变量的设置
很明显,{FOO}或者{BAR}的形式在两种模板中都是指定的形式;也就是说,两种模板处理方式中,模板文件本身的外貌应该可以是一致的(比如都是HTML文件中间含有将要被替换的以{}标识的变量)。
模板类的初始化(类的构建器)
都需要在构建模板类的时候指定模板文件存在的目录位置。
变量的替换
模板处理中最常用的就是变量替换,两种方式除了方法名不同之外(PHPLIB Template采用set_var(),而FastTemplate采用assign()),用法几乎也是一致的--可以采用(key, value)的方式,也可以直接传递一个数组(array(key=>value))。
模板文件的处理
都是采用为每一个模板文件指定一个句柄(handler)的办法,同时句柄也可以作为变量的值替换另一模板文件中的变量。
解析、输出过程
都是需要调用parse()方法(这个方法名竟然是相同的)将需要输出的模板文件解析后赋值给一个句柄,然后调用各自输出的方法(PHPLIB Template中是p(),FastTemplate中是FastPrint())输出该句柄的内容并结束处理。
重复解析的过程
比如从数据库中取出几条记录需要显示而模板文件只有可替换的一行变量的时候,就很需要这样的功能。两者都具有这样的功能,只是使用时稍稍有些不同而已(PHPLIB Template采用parse(handler, value, true),而FastTemplate采用parse(handler, .value)在值的前面多加一个点),应该说PHPLIB Template的方法构造得相对优美一点。
区块解析的过程(或者可以称作动态解析)
想像一下你需要从数据库中取出符合条件的数据并显示在网页中--但是因为条件会不尽相同,你并不能明确的知道会有多少条数据--这时候如果你又要采用模板,那么区块就是最好的选择。它是在模板中用特定的符号定义的部分,这一部分可以反复的被解析并添加到(而不是前一次的解析被后一次覆盖)输出网页中。区块也许就像下面显示的一样(左边是PHPLIB Template采用的区块设置,而右边则是FastTemplate采用的):
好吧,如果你对以上苍白的文字介绍还是有些摸不着头脑,那么我们就来看看两个详尽的模板处理的例程吧!(如果你有兴趣对后面的测试代码进行发掘,就会发现其实以下的两个例子都来自那里)
怎么样,是不是感觉几乎是一致的?下面是区块解析的例子,你也会发现同样的效果:
我们的测试目标和结果
结束了对PHPLIB Template和FastTemplate的了解,应该可以进入本文的正题了--在应用环境中当然应该选择易于使用同时速度理想的部件构建系统,那么对于这样的两种类似技术,进行评测非常有必要。评测应该是由两部分组成:技术的使用难度和速度的快慢程度--前者是评论的部分,而后者是测试的部分。对于前者,我们主要针对两个类提供的API进行评论;对于后者,我们会让测试的数据来说话,当然这中间免不了需要编写一些简单的测试代码。
回合一:技术的易用性
这一回合主要是探讨PHPLIB Template和FastTemplate提供的API的使用情况。应该说,前者提供的API更符合PHP的一些常见编码惯例(特别是当你的项目中采用了PHPLIB的其他类时,这样的规范性会对整个项目有好的影响);而后者的一些方法名总觉得有些别扭(希望你不要觉得这只是我的狭隘看法,比如FastPrint()等等),同时方法的参数也不是非常"地道",这一点你也可以从刚才的代码看出来。
另外一点需要指出的是,对于模板区块的解析,FastTemplate直到最近的版本才开始支持。也就是说,如果你采用了之前的版本,在处理诸如数据库中记录的输出等内容时,不得不把这块内容独立存储在某处,然后在模板分析处理时附加上这个文件--真是一件让人难受的事情,尤其是对网页设计人员而言。
当然还有一点需要考察--那就是对于PHP版本的支持。PHPLIB产生在PHP3的时代,这一点和FastTemplate差不多;但是根据我们的应用,PHPLIB在现在的PHP4环境下运行相当好,而FastTemplate的网页上则显示了一些信息表明对于PHP4也许它还有一些BUG存在。
好了,讲了这么多(也许你会觉得都是FastTemplate的坏话),这个回合的胜利者很明显:PHPLIB Template,尤其是你同时在使用PHPLIB的其他类时,这样的技术易用性更加明显(你将不会对这些出自同一个开发小组的API感到陌生)。
回合二:处理速度
也许这才是很多人最关注的部分--在这个回合中,我们会采用两种模板处理的方式:一种是常规的分析、替换,另一种是对区块的解析、替换--同时这样的两种方式也是在实际系统中应用最多的:前者是一般的页面处理,后者是关于数据库内容的输出处理。同时,由于两种模板类采用的模板文件的格式基本相同,使得我们可以提供几乎一致的模板文件分别供两种模板解析,更增加了测试的可信度。
开展这样的速度测试之前会拟定一个测试方案,简单说来就是对于两种处理方式分别编写两个PHP测试页面,同时有一个控制测试的页面多次调用这两个页面并记录时间供采集测试数据。(如果有兴趣你还可以参考以下详细的测试方案,也许会对你深入了解这次测试有所帮助)
小结--在整个测试系统完成之后,我们应该能够得到/test目录中如下的文件清单:
(有点复杂的测试方案)
首先是确定测试的硬件和软件环境--硬件肯定是自己的机器了,Intel Celeron 733MHz, 256M RAM,40G HDD;软件平台中OS为Win2K Pro,Web服务器为Apache+PHP,且以模块方式运行。
其次是规划这次测试的系统--当然先在Web服务器的文档根目录下开一个tpl_test的新目录用以放置这个测试的所有文件;然后在/tpl_test下建立include目录以存放两个模板类文件(我们测试的核心,以.inc.php为文件扩展名)以及一个测试类文件(包括了计时和记录日志以及读取日志并分析等功能,以.inc.php为文件扩展名)和一个数据文件(为区块解析的测试做准备,主要包含了一个二维数组,同样以.inc.php为文件扩展名),建立ihtml目录存放使用的模板文件(需要被解析的模板文件,以.ihtml为文件扩展名),建立logs目录存放测试产生的日志(后面就是发现,其实测试的数据就是由对这些日志的分析得到的,以.log为文件扩展名)。当然,两种模板的处理PHP文件就放在/test目录下。这次测试最关键的一点是,还需要建立一个PHP文件,对以上提到的负责模板处理的文件进行数次调用:比如一个文件fast_test.php是采用FastTemplate解析模板的,而phplib_test.php是采用PHPLIB Template解析的,那么这个得出结果的PHP文件就负责多次以HTTP的方式请求以上的两个页面以获得测试数据。
选择待解析的模板和PHP程序编写--因为两种模板处理方式对于模板文件本身的格式要求几乎一致(比如待替换变量都采用{VAR}的形式等等),因此可以尽量保证同一测试中两者选用的模板尽可能相同以谋求测试的最大公正性;同时在前文提到,为模拟现实系统中常用的两种模板应用:一般的页面处理和对数据库内容的输出处理,测试使用的模板文件也分成两种:一种是普通的带有一些待替换变量的模板文件,另一种是带有区块的需要根据应输出的内容反复替换的模板文件。同样对于这两种模板文件,也需要分别编写两种不同的PHP文件进行解析。
测试方法--在浏览器中向/test/result.php提出请求,需要带参数type=[simple complex],在返回的结果中即可看到两种模板在简单或者复杂模式下的测试结果。
Level 1 Level 2 Level 3 Remark
/test 测试系统的根目录
result.php 进行测试并产生结果的PHP文件,测试时只需要在浏览器中请求该页面即可获得测试信息
simple__test_phplib.php 使用PHPLIB Template对一般模板进行分析的PHP文件
simple__test_fast.php 使用FastTemplate对一般模板进行分析的PHP文件
complex__test_phplib.php 使用PHPLIB Template对带区块模板进行分析的PHP文件
complex__test_fast.php 使用FastTemplate对带区块模板进行分析的PHP文件
/include 包含PHP类文件.inc.php
phplibTemplate.inc.php PHPLIB Template类文件
FastTemplate.inc.php FastTemplate类文件
TplTest.inc.php 测试中需要使用的测试类,包含诸如计时、读取/分析日志等方法。
data.inc.php 测试带区块模板时采用的数据文件。
/ihtml 包含模板文件.ihtml
simple_phplib.ihtml 采用PHPLIB Template处理的一般模板文件
simple_fast.ihtml 采用FastTemplate处理的一般模板文件
complex_phplib.ihtml 采用PHPLIB Template处理的带区块的模板文件
complex_fast.ihtml 采用FastTemplate处理的带区块的模板文件
/logs 包含日志文件.log
simple_phplib.log 采用PHPLIB Template处理一般模板生成的日志
simple_fast.log 采用FastTemplate处理一般模板生成的日志
complex_phplib.log 采用PHPLIB Template处理带区块模板生成的日志
complex_fast.log 采用FastTemplate处理带区块模板生成的日志
经过了测试系统的设计和编写,并且向负责网页设计的同事讨来两个模板之后,我们就可以访问这个系统了--前期的辛勤劳动使得现在观看结果的工作只需要在浏览器的地址栏中打入 http://localhost/tpl_test/result.php?type=[simple complex] (如果你是在其他的非本地服务器中进行这个测试,那么域名应采用所在服务器的域名--比如我自己的机器叫做patrick等等)。下面是我自己在某一次的测试中获得的结果:(测试结果数据解释)
名称 解释 备注
amount 测试总数(连续请求该页面总数) 该参数可在result.php文件中修改
max_seq 最大处理时间的序号 范围在1-amount之间
max_value 最大处理时间的值 峰值数据供参考
min_seq 最小处理时间的序号 范围在1-amount之间
min_value 最小处理时间的值 峰值数据供参考
average 平均处理时间 测试中最有价值的数据
当然,如果你觉得一次测试的结果并不可靠,可以反复按下浏览器的刷新按钮,就能够观察到不同测试的结果(理论上应该是相差无几)。
测试结果以及颁发"XX选择奖"
好了,在偏重速度测试的回合二中PHPLIB Template以惊人的2倍的速度战胜了FastTemplate;而同时在第一回合中PHPLIB Template有以良好的API设计和易用性占得上风。结果显而易见--我们的选择奖当然颁发给了PHPLIB Template,同时这次的测试也让我们对PHPLIB这个类库设计有了更深的了解。
主观评价
既然有了结果,那么FastTemplate自然也就不能进入我们的项目了--虽然从结果上看来我们花费了半天的时间得到了一个毫无变化的结果(PHPLIB Template继续很好的在项目中使用),但是测试的过程却是很有价值的,特别是采用PHP进行测试的方法,应该会在以后的类似决策中起到一定参考作用。
参考资料
本文中的测试代码下载 (article_256.zip)
介绍PHPLIB Template和FastTemplate的著名文章
Templates, The PHPLIB Way
by David Orr, May of 2000
(http://www.phpbuilder.com/columns/david20000512.php3 )
(PHPLIB Template)
Templates - why and how to use them in PHP3
by Sascha Schumann, March of 1999
(http://www.phpbuilder.com/columns/sascha19990316.php3 )
(FastTemplate)
PHPLIB Template和FastTemplate的主页
PHP Library Homepage
(http://phplib.netuse.de )
FastTemplate Homepage
(http://www.thewebmasters.net/php/FastTemplate.phtml )
其他模板处理文章以及其他关于PHP的资料
PHP Builder (http://www.phpbuilder.com )
以上文章的中文译本以及其他的中文PHP资料
PHP中文用户(http://phpuser.com )
……