收藏文章 楼主
[PHP]超越模板引擎
网友【血蜘蛛】 2005-06-21 04:17:35 分享在【时代发展的印记】版块    1    1
作者:Brian Lozier

译者:taowen

In general, template engines are a "good thing."

总体来说,模板引擎是一个"好东西"

作为一个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} 比 更加简单?如果你认为这样简单一些,问问你自己是不是在包含一个巨大的模板库来到成这种分离时能够看到真正的意义要更加简单一些。诚然,Smarty提供了许多其他很好的特性,但是看上去这些益处能够在不用承担包含Smarty类库的情况下也能获得。

别样的解决方案

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

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

当我认为这种方法比经典的模板引擎要高明得多时,肯定还有一些要商榷的问题。最明显的反面意见是,PHP代码太复杂了,而且设计者不应该强迫去学习PHP。事实上,PHP代码和像Smarty这样的高级模板引擎的语法差不多简单(如果不是更简单的话)。而且,设计者能够使用像这样的简写PHP。这要比{$var}复杂很多?当然,这要长一些,但是如果你习惯了,你能够获得了PHP的威力而且不用承受解析模板文件带来的负担。

第二,而且可能更重要的,在基于PHP的模板中没有固有的安全。Smarty提供了选项在模板文件中彻底禁用PHP代码。它使得开发者能够约束模板能够访问的函数和变量。如果你没有不怀好意的设计者,这不会是什么问题。然而,如果你允许外部的用户上传或者修改模板,我在此展示的基于PHP的解决方案绝对没有任何安全可言!任何代码都能放入模板中并且得到运行。是的,甚至是一个print_r($GLOBALS)(这将改有恶意的用户访问脚本中任何变量的权利)。

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

例子

这是一个简单的用户列表页面的例子。

代码:require_once('template.php');

/**
* This variable holds the file system path to all our template files.
*/
$path = './templates/';

/**
* Create a template object for the outer template and set its variables.
*/
$tpl = & new Template($path);
$tpl->set('title', 'User List');

/**
* Create a template object for the inner template and set its variables. The
* fetch_user_list() function simply returns an array of users.
*/
$body = & new Template($path);
$body->set('user_list', fetch_user_list());

/**
* Set the fetched template of the inner template to the 'body' variable in
* the outer template.
*/
$tpl->set('body', $body->fetch('user_list.tpl.php'));

/**
* Echo the results.
*/
echo $tpl->fetch('index.tpl.php');
?>

其中有两个值得注意的重要的概念。第一个就是内部和外部模板的概念。外部模板包含定义站点主要外观的HTML代码。而内部模板包含定义站点内容区域的HTML代码。当然,你能够在任意数目的层上有任意数目的模板。因为通常我们给每个区域使用不同的模板对象,所以没有名字空间的问题。例如,我能在内部和外部模板中都有变量叫"title",而不用害怕有什么冲突。

这是一个用来显示用户列表的模板的简单例子。注意特殊的foreach和endforeach;语法在PHP手册中有说明 [8]。它完全是可选择的。

而且,你可能奇怪我为什么要用.php的后缀来命名我的模板文件。呵呵,许多PHP字节码缓存解决方案(比如 phpAccelerator)如果要被认成PHP文件,需要文件有一个.php后缀。因为这些模板是PHP文件,为什么不去获得这些好处?

代码:














IdNameEmailBanned
">


这个layout.tpl.php是一个简单的例子(定义了整个页面看上去是什么样子的模板文件)

代码:

<?=$title;?>







And here's the parsed output.

而这是解析后的输出。

代码拷贝框

代码:

User List




User List








































IdNameEmailBanned
1bob[email protected]
2judy[email protected]
3joe[email protected]
4billy[email protected]X
5eileen[email protected]




Caching

缓存

因为解决方案简单如斯,实现模板缓存成为了一个非常简单的任务。为了实现缓存,我们有一个二级类,它扩展了原来的模板类。CachedTemplate类事实上使用和原来的模板类相同的API。不同点是我们必须传递缓存的设置给构造函数,并且调用fetch_cache()而不是fetch()。

缓存的概念是简单的。简单的说,我们设置一个缓存时间来调表输出应该被保存的时长(以秒为单位)。在产生一个页面的所有工作开展之前,我们必须首先测试页面是否已经被缓存了,而且缓存是否仍然没有过期。如果缓存在这那,我们不需要在去麻烦数据库和业务逻辑来产生页面——我们可以简单地输出原先缓存地内容。

这种方法需要解决唯一地标识缓存文件的问题。如果一个站点是被一个显示基于GET变量的中心脚本所控制,对每个PHP文件只有一个缓存不会有什么帮助。例如,如果index.php?page=about_us和用户调用index.php?page=contact_us得到的显示完全不同。

问题是通过给每个页面产生一个唯一的cache_id来解决的。为了做到这个目的,我们把事实上被请求的文件变成REQUEST_URI(基本上就是整个URL:index.php?foo=bar&bar=foo)。当然,这个转换过程是受到CachedTemplate类控制的,但是要记住的重要的事情是你绝对要在创建CachedTemplate对象时传递一个唯一的cache_id。当然下面有例子来说明。

使用缓存包括以下步骤。

include() 模板源文件

创建一个新的CachedTemplate对象(并且传递路径,唯一的cache_id和缓存过期时间给模板)

测试内容是否已经被缓存了

如果还促拿了,显示文件并且结束脚本

否则,进行所有的处理并且fetch()模板

对fetch_cache()的调用将自动产生一个新的缓存文件

这个脚本假定你的缓存文件将放到./cache/中,因此你必须创建那个目录并且改变它的目录权限(chmod)使得Web服务器能够写入文件。而且还要注意如果你在编写脚本的过程中发现了错误,错误也会被缓存!因而在你开发的过程中禁用缓存是一个好主意。最好的办法是给cache的生存周期传递0——这样,缓存总是立即就失效了。

由于排版需要,请点击以下地址查看全文:

noasia.net/taowen/translatio...te%20Engine.htm

出处:CSDN
meiguo.com 发布人签名/座右铭·有时你看似是一件很吃亏的事,往往会变成非常有得的事。
·凡事都留有余地,因为人是人,不是神,不免有错处,可以原谅人的地方,就原谅人。
·好的时候不要看得太好,坏的时候不要看的太坏。
大家都在看
回复/评论列表
默认   热门   正序   倒序
meiguo.com 创始人

emotion

1   2005-06-21 04:17:35  回复

回复/评论:[PHP]超越模板引擎

暂无用户组 升级
退出
等级:0级
美果:
美过
精华推荐
  1. 从旧金山到洛杉矶,美国西部旅行的完整实录
  2. 新罕布什尔州的一位女子在领取彩金的现场捐出5000万美元
  3. 号外:伊隆·马斯克的第11个孩子出生了
  4. “走线”路不通了?拜登政府颁布最严边境令?
  5. 人身安全“没保障”的原因?赴美留学的趋势遇冷
  6. 苹果公司在2024秋季的新品发布会(懒人速览)
  7. 美国人口流动数据剖析:年轻富有群体搬家去哪儿了?
  8. 关于美国的社保(全面解读)
  9. 关于EVUS的填写心得和常见问题
  10. 五星红旗在月球背面升起!阿波罗登月遭遇再度质疑?
  11. 回归之王:唐纳德·特朗普“赢得又大又快”
  12. 世上只有男人和女人!~ 特朗普总统:上帝只创造了两种性别,无其它!
  13. 中国人即将登月!
  14. 移民故事:入赘美国的河南保安【蔡小华】现状
  15. 在加州海滩捡蛤蜊,72个罚9万美元!
  16. 关于美国大学的学费开支
  17. 伊隆·马斯克在“We, Robot”三连发:Cybercab、Robovan及Optimus!
  18. 美国房市降温?待售房屋开始下调要价!
  19. 悲惨回顾:美国历史上的十大枪击案盘点
  20. “极右翼”控制移民政策!特朗普政府的内阁名单曝光
  21. 《黑神话:悟空》发行仅3小时后竟然就这样了!
  22. 深入剖析:性在人类交往中的作用
  23. 完整曝光:美国前总统【川普(特朗普)】遭遇刺客的前前后后
  24. 《潜望》对话李开复:如果美国形成AGI霸权,中国咋办?
  25. 中国防长:“谁胆敢把台湾从中国分裂出去,必将粉身碎骨、自取灭亡”
  26. 漂亮国再次遣返中国移民,这批有131人!
  27. 宁愿混居美国,华人姑娘袒露了不愿回国的真相!
  28. 巨型公司:市值已超3.5万亿美元,约合18个阿里巴巴!
  29. 佛罗里达遭遇的飓风可以影响到美国大选结果?
  30. 坐火车“游览全美国”的14条线路盘点
  31. 福建人在纽约:有多少人通过走线(偷渡)到纽约的?
  32. 拆解:太精致啦!到底是苹果M4 Mac mini牛?还是华强北更牛?
  33. 加州公司的市值盘点 top10
  34. 能决定2024选举结果?特朗普即将放大招了!
  35. 珠海航展:轰20的先行版遭遇美国酸溜溜了
  36. 碧昂斯和巨石强森这样的美国巨星在大选中,如何站队的?

美国动态 美果转盘 美果商店

Your IP: 52.14.27.122, 2024-11-26 19:45:35

Processed in 0.48205 second(s)

头像

用户名:

粉丝数:

签名:

资料 关注 好友 消息
已有0次打赏
(1) 分享
分享
取消