`
hanssonlan
  • 浏览: 13162 次
  • 性别: Icon_minigender_1
  • 来自: 广州
最近访客 更多访客>>
社区版块
存档分类
最新评论

PHP沉思录之三:Smarty

    博客分类:
  • php
阅读更多
  在任何Web应用中,如何将程序代码和界面设计,或者说,将逻辑层和表现层分离开来,都会是一个问题。对于PHP这种类型的嵌入网页的脚本语言,这一问题尤其突出。在新手编写的代码中,把访问数据库的代码和操纵HTML元素的代码写在同一个页面里,是很常见的情况。为了避免这一问题,开发者倾向于将涉及业务逻辑的代码封装在某些单独的库文件中,再在负责显示界面的文件中将它们include进来。但是,这仍然无法避免在显示界面的文件中包含大量的PHP代码。究其所以然,是因为除了涉及业务逻辑的代码以外,即使仅仅在显示层,也往往涉及到复杂的显示逻辑。在一个典型的显示页面中,程序需要先包含所有必需的库文件,初始化上下文环境,创建相关业务逻辑对象(假如数据库访问代码已经被业务逻辑对象封装,可以节省数据库相关的代码),最后在HTML的空隙中把对象格式化为HTML元素进行显示。于是我们看到了无数这样的页面,在第一行HTML开始之前,就已经包含了数十行甚至更多的PHP代码,在HTML的内部,仍然充满了各种各样的PHP代码。因此,PHP代码和HTML代码搅和在一块的问题仍然无法解决,对HTML的修改仍然可能导致整个PHP程序崩溃。更加麻烦的是,这种不清晰的结构妨碍了PHP应用在规模上的进一步扩张。

        为了解决这一问题,模板(template)技术应运而生。模板技术的基本原理是,通过一个解析器(parser),读取指定的模板文件(包含了某些特定标签的HTML文件),将这些标签替换为相关的PHP变量,再输出为标准的HTML。通过这种方式,不但分离了业务逻辑层和表现层,而且也尽可能地分离了显示逻辑和HTML代码。通过替换不同的模板文件,可以方便地生成各种格式的输出,例如HTML,XML,WML,后期稍加处理甚至可以生成PDF和 Flash。早期较为著名的PHP模板引擎有PHPLib中的Template和FastTemplate。

        但是,模板技术也有其先天的缺陷。
  
        无法彻底分离逻辑。显示逻辑和HTML代码很难通过简单的标签替换,实现彻底的分离。例如,遍历并显示一个数组,在PHP中可以用简单的foreach语句实现,但是使用模板时,就需要进行对整个模板文件进行多次替换操作,造成效率的极大降低;或者根据不同的数据值显示不同的格式,如果模板文件完全不包含 PHP代码,那么将很难做到这一点。

        解析导致的性能损失。由于每次PHP页面被访问时,解析器都必须对模板文件进行替换操作,无疑会降低PHP应用的性能。尤其在多次的替换操作时更是如此。因此,不使用模板比使用模板往往更加快速,这也是许多PHP程序员摒弃模板技术的原因之一。
  
       在经过数年的发展之后,“编译型”的模板技术渐渐占据了主流。所谓“编译型”,是指解析器读取模板文件以后,并不直接生成静态HTML,而是 “编译”成一个新的PHP文件,并将它保存起来。以后访问该页面时,模板引擎会直接执行“编译”后的PHP文件。Smarty是这种模板引擎的代表。

        针对以上的两个问题,Smarty作了如下处理:
  
        独立语法。Smarty实现了一套自己的语法,这套语法不但支持变量替换和简单的判断,而且支持循环,修饰符(modifier),内置了很多功能强大的函数,而且还支持自定义函数。这套系统保证Smarty能够完全独立地处理显示输出,无须再和PHP有什么瓜葛。事实上,在Smarty模板中,是不可以直接使用PHP代码的(通过显式定义可以使用),这也是一种强制分离逻辑层和表现层的方式。(理论上来说,Smarty的模板文件也可以应用于其它语言。)但是,这种解决方式也受到了指责,因为Smarty的语法过于强大,几乎变成了一门新的语言,指责者认为,这反而增加了复杂性。但是,根据作者的实际经验,Smarty的语法不但非常简单直观,而且只需要掌握一些最初级的语法,就足可以应付绝大多数的应用。即使是不懂编程的网页设计师,也很容易就能够掌握。

        编译机制。Smarty的“编译”机制,节省了用于反复解析模板文件的时间,极大地提高了速度。由于“编译”后生成的是标准的PHP文件,因此从理论上来说,执行的速度不会低于没有模板的PHP应用的速度。在一些和解析型模板引擎进行的对比测试中,Smarty在第一次访问时落后,但是在以后的访问中速度远远超出竞争对手。而且,这种编译过程是智能的,在模板文件的内容被改变后,Smarty会自动重新编译,因此对于开发者来说,编译过程完全无需人工干预。另外,如果你愿意的话,生成的PHP文件还可以方便地应用于Zend Accelerator这样的工具,进行二次编译。
  
        除此之外,Smarty还拥有其他一些优秀的特性:
  
        缓存机制。由于实现了编译机制,在接收到对某个模板文件的访问请求时,Smarty会自动将它重定向到编译后的PHP文件。但是,这也意味着,Smarty也可以将它重定向到任何其他的文件——例如静态的HTML文件。在此基础之上,Smarty实现了自己的基于页面的缓存机制。 Smarty能够将编译后的PHP文件产生的结果——静态HTML——保存起来,将重复发送的请求直接重定向给它,这意味着对于第一次之后的请求,不需要执行任何PHP代码(Smarty本身的代码当然除外)。对于不需要频繁更新的页面(我们知道这种网页往往在整个网站中占大多数),通过这种缓存机制获取的性能提升是惊人的。而且,由于它是在页面级实现的,因此完全无须涉及到复杂的对象级缓存问题,保持了逻辑上的简单性。

        可配置性。Smarty在开发之初就将高度的可配置性作为自己的一个设计目标。它本身以100%的PHP编写,以源代码的方式发行,只需要将Smarty 简单地拷贝到你的文件路径中,就可以使用了。Smarty的各项配置变量,都可以通过修改config文件或者手动编码进行定制。例如,Smarty默认的定界符是花括号({}),但是这往往和Javascript以及CSS中的花括号冲突。为了解决这一问题,可以简单地将默认定界符修改为其他的字符(例如ASP风格的“<%”和“%>”)。

        可扩展性。Smart的实现基于面向对象的架构,并且提供了插件机制,非常便于用户修改和扩展其默认的认为。当然,你也可以直接修改它的源代码来达到目的。(对于基于脚本语言的开源应用来说,这是非常惬意的,因为你甚至不需要重新编译。)
  
        让我们来看一个最简单的Smarty应用。这个应用包括两个文件:
  
        TestSmarty.php 调用Smarty类库,初始化变量,并解析相应的模板文件
        TestSmarty.tpl 模板文件,其实就是包含了Smarty标签的HTML,放在指定的模板目录下,默认是./templates
  
        TestSmarty.php的内容如下:
Html代码
    
  <?php 
  include_once("./smarty/Smarty.class.php");  
    
  $Smarty = new Smarty();  
  $Smarty->assign("HelloStr", "Hello, world");  
  $Smarty->display("TestSmarty.tpl");  
  ?> 

  
  <?php
  include_once("./smarty/Smarty.class.php");
  
  $Smarty = new Smarty();
  $Smarty->assign("HelloStr", "Hello, world");
  $Smarty->display("TestSmarty.tpl");
  ?>
  

        这个文件的内容非常简单,任何有过PHP经验的程序员都应该能够理解:首先将Smarty类库所在的文件include进来,然后创建一个新的Smarty对象,并对HelloStr变量进行赋值,最后解析TestSmarty.tpl文件。
        TestSmarty.php的内容如下:
  
Html代码
This is a string from Smarty: {$HelloStr} 

This is a string from Smarty: {$HelloStr}
  
   解析的结果为:
  
Html代码
This is a string from Smarty: Hello, world 

This is a string from Smarty: Hello, world
  
   此时检查存放编译后的PHP文件的子目录(默认是./templates_c),可以找到一个名叫%%65^650^65099D8B%%TestSmarty.tpl.php的文件,内容如下:
  
<?php /* Smarty version 2.6.18, created on 2007-08-12 03:04:56
compiled from TestSmarty.tpl */ ?>
This is a string from Smarty:
<?php echo $this->_tpl_vars['HelloStr']; ?>
  
        这就是Smarty引擎编译生成的结果。
        为了启用缓存,可以在TestSmarty.php文件中加入这么一行(当然必须在display方法之前):
  
Html代码
$Smarty->caching = 1; 

$Smarty->caching = 1;
  
        重新访问该页面,然后检查存放缓存文件的子目录(默认是./cache),可以找到一个名叫%%65^650^65099D8B%%TestSmarty.tpl的文件,内容如下:
  
    136
   a:4:{s:8:"template";a:1:{s:14:"TestSmarty.tpl";b:1;}s:9:"timestamp";i:1186888266;s:7:"expires";i:1186891866;s:13:"cache_serials";a:0:{}}This is a string from Smarty: Hello, world
  
        这就是生成的缓存文件,在静态的HTML文件之前,包含了已经序列化的PHP信息。虽然这些信息无法被直接阅读,但是多少还是能够猜测出来:模板的子目录,模板文件名,时间戳,生存期(过期时间),等等。如果读者有兴趣研究它们的详细定义,可以阅读Smarty的源代码。
        注意,上述信息中包含了一项:生存期,即当前缓存在多长时间以后过期。Smarty默认的生存期是1小时,即3600秒。可以通过修改Smarty属性来设置生命期,代码如下:
  
Html代码
$Smarty->cache_lifetime = 1800; 

$Smarty->cache_lifetime = 1800;
  
        时间单位是秒,设置为1800表示当前缓存半小时后过期。
        Smarty还支持为同一个模板创建多个缓存实例,这在实际应用中是非常常见的。举例来说,假设某个博客系统中,显示article的页面为 Article.php,对应的模板文件为Article.tpl。但是,article页面的内容根据不同的article ID而不同,因此,必须为同一个页面创建不同的缓存实例。Smarty可以轻松做到这一点:
  
Html代码
$Smarty->display("Article.tpl", $ArticleId); 

$Smarty->display("Article.tpl", $ArticleId);
  
        只要将一个唯一标识符(在这个例子中是article的ID)作为第二个参数传给display方法,Smarty就会自动完成一切。
  
        Smarty出现的时间虽然较老牌的PHPLib Template和FastTemplate为晚,但是发展非常迅速,而且已经成为PHP的官方子项目,拥有二级域名http://smarty.php.net/。正如它的官方站点上所说,与其说Smarty是一个模板引擎,不如说它是一个表现层的Framework。这句话极为重要。

        作者个人认为,Smarty诞生和逐渐取得主流地位的意义,不仅仅是提供了一个优秀的模板引擎,而是表示PHP在解决更大规模的应用上迈出了坚实的一步。如果说Java是一开始就将解决大规模应用作为自己的设计目标的话,那么PHP就是在开源社区的推动下,在不断的改进中逐渐接近这一目标。当一个PHP应用采用了Smarty这样优秀和成熟的表现层解决方案,以及其他一些类似的技术(例如好的ORM解决方案)以后,它能够解决的问题的规模就比过去大得多了。通过这些现象,我们可以看到,PHP,或者说LAMP,正在以稳健而持续的步伐,向企业级应用迈进。
分享到:
评论

相关推荐

    PHP Smarty 用户登录系统

    PHP Smarty 用户登录系统 PHP Smarty 用户登录系统

    php之smarty入门

    php之smarty入门

    smarty模板中文手册

    2. 编译型:采用Smarty编写的程序在运行时要编译成一个非模板技术的PHP文件,这个文件采用了PHP与HTML混合的方式,在下一次访问模板时将WEB请求直接转换到这个文件中,而不再进行模板重新编译(在源程序没有改动的...

    php模版 (smarty)php模版 (smarty)php模版 (smarty)

    php模版 (smarty)php模版 (smarty)php模版 (smarty)php模版 (smarty)php模版 (smarty)php模版 (smarty)php模版 (smarty)

    PHP100视频教程 30:PHP模板引擎Smarty缓存应用

    1、Smarty缓存的配置 $smarty-&gt;cache_dir = "/caches/"; //缓存目录 $smarty-&gt;caching = true; //开启缓存,为flase的时侯缓存无效 $smarty-&gt;cache_lifetime = 60; //缓存时间2、Smarty缓存的使用和清除 $...

    Smarty 2.6.18

    php smarty模板引擎 版本: smarty 2.6.18

    smarty3 的应用详解

    $smarty= Smarty::instance(); 模板 之前的smarty模板,相当于重新定义了一套标签语言,那么smarty3提供了一种新的模板形式,直接支持php语法的模板。 但是问题就出来了,我们还有必要用模板吗? 引用php类型模板...

    Smarty 2.6.24

    php Smarty 模板 版本:Smarty 2.6.24

    PHP之Smarty入门

    菜鸟学PHP之Smarty入门 php入门级教程 手把手教你学会smarty

    PHP-Smarty模板笔记

    Smarty是一个使用PHP写出来的模板引擎,是业界最著名的PHP模板引擎之一。Smarty分离了逻辑代码和外在的内容,提供一种易于管理和使用的方法,用来将原本与HTML代码混杂在一起PHP代码逻辑分离。Smarty工作的目的是要...

    smarty-3.1.29

    2015年12月24日最新版:smarty-3.1.29

    php之Smarty模板引擎

    php Smarty

    PHP—Smarty模板

    Smarty是一个使用PHP写出来的模板引擎,是目前业界最著名的PHP模板引擎之一。它分离了逻辑代码和外在的内容,提供了一种易于管理和使用的方法,用来将原本与HTML代码混杂在一起PHP代码逻辑分离。简单的讲,目的就是...

    smarty调用php常量

    smarty调用php常量

    菜鸟学PHP之Smarty入门

    菜鸟学PHP之Smarty入门菜鸟学PHP之Smarty入门

    DZ论坛 PHP插件开发[基于Smarty]

    DZ论坛 PHP插件开发[基于Smarty]DZ论坛 PHP插件开发[基于Smarty]DZ论坛 PHP插件开发[基于Smarty]DZ论坛 PHP插件开发[基于Smarty]DZ论坛 PHP插件开发[基于Smarty]DZ论坛 PHP插件开发[基于Smarty]DZ论坛 PHP插件开发...

    PHP100视频教程 29:PHP模板引擎Smarty内置函数

    在实际操作中与section 功能一样,但foreach在Smarty一般用来处理一维数组。2、include 多功能使用3、IF条件语句的使用4、literal strip 文本的处理技巧 literal 数据将被当作文本处理,此时模板将忽略其内部的所有...

    php+smarty输出新闻列表

    php+smarty输出资讯列表,生成html静态

    php4、php5帮助文档及smarty帮助文档

    内含: PHP4 中文参考手册 PHP4完全中文手册 PHP5学习(全英文) PHP编码规范 PHP的一些例程 PHP手册 php手册-PHP5研究室编译 无乱码版本 smarty中文手册

    Smarty.class.php

    Smarty是一个使用PHP写出来的模板引擎,是目前业界最著名的PHP模板引擎之一。它分离了逻辑代码和外在的内容,提供了一种易于管理和使用的方法,用来将原本与HTML代码混杂在一起PHP代码逻辑分离。简单的讲,目的就是...

Global site tag (gtag.js) - Google Analytics