Smarty处理页面缓存

用户在每次访问PHP应用程序时,都会建立新的数据库连接并重新获取一次数据,再经过操作处理形成HTML等代码响应给用户。所以功能越强大的应用程序,执行时的开销就会越大。这是由于HTTP协议的无状态性造成的,对于每次页面的请求,都要重复地执行相同的操作,而不论数据是否被修改。但有些信息比如经常不变的,但是还是能变的信息。如果不想每次都重复执行相同的操作,就可以在第一次访问PHP应用程序时,将动态获取的HTML代码保存为静态页面,形成缓存文件。在以后每次请求该页面时,直接去读取缓存的数据,而不用每次都重复执行获取和处理操作带来的开销。这样,不仅可以加快页面的显示速度,而且我们在保存时通过指定下次更新的时间,也能达到缓存被动态更新的效果。比如需要60分钟更新一次,就可以根据记录的上次更新时间和当前时间比较,如果大于60分钟,重新读取数据库并更新缓存,否则还是直接读取缓存数据。所以,让Web应用程序运行得更高效,缓存技术是一种比较有效的解决方案。

16.8.1  Smarty中控制缓存

Smarty缓存与前面介绍的Smarty编译是两个完全不同的机制,Smarty的编译功能在默认情况下是启用的,而缓存则必须由开发人员显示开启。编译的过程是将模板转换为PHP脚本,虽然Smarty模板在没被修改过的情况下,不会再重新执行转换过程,直接执行编译过的模板。但这个编译过的模板其实就是一个PHP脚本,只是减少了模板转换的开销,仍需要在逻辑层执行获取数据所需的动作,而这个动作执行开销是最大的。缓存则不仅将模板转换为PHP脚本执行,而且将模板内容转换成为静态页面,所以不仅减少了模板转换的开销,也没有了在逻辑层执行获取数据所需的开销。

1.建立缓存

如果需要使用缓存,首先要做的就是让缓存可用,这就要设置Smarty对象中的缓存属性,如下所示:

<DIV align=center>

<?php

         require('libs/Smarty.class.php');                               //包含Smarty类库

         $smarty = new Smarty;                          //创建Smarty类的对象

         $smarty->caching = true;                         //启用缓存

         $smarty->cache_dir = "./cache/";                   //指定缓存文件保存的目录

         $smarty->display('index.tpl')                     //也会把输出保存

?>

</DIV>

在上面PHP脚本中,通过设置Smarty对象中的$caching = true(或1)启用缓存。这样,当第一次调用Smarty对象中的display('index.tpl')方法时,不仅会把模板返回原来的状态(没缓存),也会把输出复制到由Smarty对象中的$cache_dir属性指定的目录下,保存为缓存文件。下次调用display('index.tpl')方法时,保存的缓存会被再用来代替原来的模板。在$chche_dir目录里的文件命名跟模板一致,尽管是用.php作为扩展名,但并不会被当做php代码来解析,所以不要去修改它。         

2.处理缓存的生命周期

如果被缓存的页面永远都不更新,就会失去动态数据更新的效果。但对一些经常不变的,但还是需要改变的信息,我们可以通过指定一个更新时间,让缓存的页面在指定的时间内更新一次。缓存页面的更新时间(以秒为单位)是通过Smarty对象中$cache_lifetime属性指定的,默认的缓存时间为3600s。因此,如果希望修改此设置,就可以设置这个属性值。一旦指定的缓存时间失效,则缓存页面将会重新生成。如下所示:

<DIV align=center>

<?php

         require('libs/Smarty.class.php');                      //包含Smarty类库

         $smarty = new Smarty;                          //创建Smarty类的对象

         $smarty->caching = 2;                           //启用缓存,在获取模板之前设置缓存生存时间 

         $smarty->cache_dir = "./cache/";                   //指定缓存文件保存的目录

         $smarty->cache_lifetime = 60*60*24*7;            //设置缓存时间为1

         $smarty->display('index.tpl');                    //也会把输出保存

?>   

</DIV>

如果你想给某些模板设定它们自己的缓存生存时间,你可以在调用display()fetch()函数之前,通过设置$caching = 2,然后设置$cache_lifetime为一个唯一值来实现。$caching必须因$cache_lifetime需要而设为true,值为-1时将强迫缓存永不过期,0值将导致缓存总是重新生成(仅有利于测试,一个更有效的使缓存无效的方法是设置$caching = false)。 

大多数强大的Web应用程序功能都体现在其动态特性上,哪些文件你加了缓存,缓存时间多长都是很重要的。例如,你站点的首页内容不是经常更改,那么对首页缓存一个小时或是更长都可以得到很好效果。相反,几分钟就要更新一下信息的天气地图页面,用缓存就不好了。所以一方面考虑到性能提升,另一方面也要考虑到缓存页面的时间设置是否合理,要在这二者之间进行权衡。

16.8.2  每个页面多个缓存

例如,同一个新闻页面模板,是发布多篇新闻的通用界面。这样,同一个模板在使用时就会生成不同的页面实现。如果开启缓存,则通过同一个模板生成的多个实例都需要被缓存。Smarty实现这个问题比较容易,只要在调用display()方法时,通过在第二个可选参数中提供一个值,这个值是为每一个实例指定的一个唯一标识符,有几个不同的标识符就有几个缓存页面。如下所示:

<DIV align=center>

<?php

         require('libs/Smarty.class.php');                              //包含Smarty类库

         $smarty = new Smarty;                                   //创建Smarty类的对象

         $smarty->caching = 1;                                    //启用缓存

         $smarty->cache_dir = "./cache/";                           //指定缓存文件保存的目录

         $smarty->cache_lifetime = 60*60*24*7;                     //设置缓存时间为1

         /*

         $news=$db->getNews($_GET["newsid"]);                  //通过表单获取的新闻ID返回新闻对象

         $smarty->assign("newsid", $news->getNewTitle());           //向模板中分配新闻标题

         $smarty->assign("newsdt", $news->getNewDataTime());      //向模板中分配新闻时间

         $smarty->assign("newsContent", $news->getNewContent);    //向模板中分配新闻主体内容

         */

         $smarty->display('index.tpl', $_GET["newsid"]);           //将新闻ID作为第二个参数提供

?>  

</DIV>

在上例中,假设该脚本通过在GET方法中接收的新闻ID,从数据库中获取一篇新闻,并将新闻的标题、时间、内容通过assign()方法分配给指定的模板。在调用display()方法时,通过在第二个参数中提供的新闻ID,将这篇新闻缓存为单独的实例。采用这种方式,可以轻松地为每一篇新闻都缓存为一个唯一的实例。

16.8.3  为缓存实例消除处理开销

所谓的处理开销,是指在PHP脚本中动态获取数据和处理操作等的开销,如果启用了模板缓存就要消除这些处理开销。因为页面已经被缓存了,直接请求的是缓存文件,不需要再执行动态获取数据和处理操作了。如果禁用缓存,这些处理开销总是会发生的。解决的办法就是通过Smarty对象中的is_cached()方法,判断指定模板的缓存是否存在。使用的方式如下所示:

<DIV align=center>

<?php

         $smarty->caching = true;                             //开启缓存

         if(!$smarty->is_cached("index.tpl")) {                   //判断模板文件imdex.tpl是否已经被缓存了

           // 调用数据库,并对变量进行赋值              //消除了处理数据库的开销

         }

         $smarty->display("index.tpl");                        //直接寻找缓存的模板输出

?>   

</DIV>

如果同一个模板有多个缓存实例的话,每个实例都要消除访问数据库和操作处理的开销,可以在is_cached()方法中通过第二个可选参数指定缓存号。如下所示:

<DIV align=center>

<?php

         require('libs/Smarty.class.php');                             //包含Smarty类库

         $smarty = new Smarty;                                    //创建Smarty类的对象

         $smarty->caching = 1;                                    //启用缓存, 

         $smarty->cache_dir = "./cache/";                          //指定缓存文件保存的目录

         $smarty->cache_lifetime = 60*60*24*7;                    //设置缓存时间为1

         if(!$smarty->is_cache('news.tpl', $_GET["newsid"])) {        //判断news.tpl的某个实例是否被缓存

/*

                   $news=$db->getNews($_GET["newsid"]);                    //获取的新闻ID返回新闻对象

                   $smarty->assign("newsid", $news->getNewTitle());           //向模板中分配新闻标题

                  $smarty->assign("newsdt", $news->getNewDataTime());      //向模板中分配新闻时间

                   $smarty->assign("newsContent", $news->getNewContent);    //向模板中分配新闻主体内容

 */

         }

         $smarty->display('news.tpl', $_GET["newsid"]);                    //将新闻ID作为第二个参数提供

?>      

</DIV>

在上例中is_cache()display()两个方法,使用的参数是相同的,都是对同一个模板中的特定实例进行操作。

16.8.4  清除缓存

如果开启了模板缓存并指定了缓存时间,则页面在缓存的时间内输出结果不变。所以在程序开发过程中应该关闭缓存,因为程序员需要通过输出结果跟踪程序的运行过程,决定程序的下一步编写或用来调试程序等。但在项目开发结束时,在应用过程中就应当认真地考虑缓存,模板缓存大大提升了应用程序的性能。而用户在应用时,需要对网站内容进行管理,经常需要更新缓存,立即看到网站内容更改后的输出结果。

缓存的更新过程就是先清除缓存,再重新创建一次缓存文件。你可以用clear_all_cache()来清除所有缓存,或用clear_cache()来清除单个缓存文件。使用clear_cache()方法不仅清除指定模板的缓存,如果这个模板有多个缓存,你可以用第二个参数指定要清除缓存的缓存号。清除缓存的示例如下所示:

<DIV align=center>

<?php

         require('libs/Smarty.class.php');

         $smarty = new Smarty();

         $smarty->caching = true;

      

         $smarty->clear_all_cache();                      // 清除所有的缓存文件

         $smarty->clear_cache("index.tpl");               // 清除某一模板的缓存

         $smarty->clear_cache("index.tpl","CACHEID");    // 清除某一模板的多个缓存中指定缓存号的一个 

 

         $smarty->display('index.tpl');

?>        

</DIV>

16.8.5  关闭局部缓存

对模板引擎来说,缓存是必不可少的,而局部缓存的作用也很明显,主要用于同一页中既有需要缓存的内容,又有不适宜缓存内容的情况,有选择的缓存某一部分内容或某一部分内容不被缓存。例如,在页面中如果需要显示用户的登录名称,很明显不能为每个用户都创建一个缓存页面,这就需要将显示用户名地方的缓存关闭,而页面的其他地方缓存。smarty也为我们提供了这种缓存控制能力,有以下三种处理方式。

Ø  使用{insert}使模板的一部分不被缓存。

Ø  可以使用$smarty->register_function($params, &$smarty)阻止插件从缓存中输出。

Ø  使用$smarty->register_block($params, &$smarty)使整篇页面中的某一块不被缓存。

如果使用register_functionregister_block则能够方便地控制插件输出的缓冲能力。但一定要通过第三个参数控制是否缓存,默认是缓存的,需要我们显示设置为false。例如,“$smarty->register _block('name', 'smarty_block_name', false);”。而insert函数默认是不缓存的,并且这个属性不能修改。从这个意义上讲insert函数对缓存的控制能力似乎不如register_functionregister_block强。最然这三种方法都可以很容易实现局部关闭缓存,但本节将介绍另一种最常用的方式,就是写成block插件的方式。步骤如下所示。

Ø  定义一件插件函数在block.cacheless.php文件中,并将其存放在smartyplugins目录中,编写该文件的内容如下:

<DIV align=center>

<?php

      function smarty_block_cacheless($param, $content, &$smarty) {

           return $content;

      }

?>

</DIV>

Ø  编写所用的模板cache.tpl文件:

<DIV align=center>

已经缓存的:{$smarty.now}

<br>

{cacheless}

         没有缓存的:{$smarty.now}

{/cacheless}

</DIV>

Ø  编写程序及模板的示例程序testCacheLess.php

<DIV align=center>

<?php

         include('Smarty.class.php');

         $tpl = new Smarty;

         $tpl->caching=true;

         $tpl->cache_lifetime = 6;

         $tpl->display('cache.tpl');

?>

</DIV>

现在通过浏览器运行一下testCacheLess.php文件,发现是不起作用的,两行时间内容都被缓存了。这是因为block插件默认也是缓存的,所以还需要改写一下Smarty的源代码文件Smarty _Compiler.class.php,在该文件中查找到下面一条语句:

<DIV align=center>

$this->_plugins['block'][$tag_command] = array($plugin_func, null, null, null, true);

</DIV>

可以直接将原句的最后一个参数改成false,即关闭默认的缓存。现在清除一下template_c目录里的编译文件,重新再运行testCacheLess.php文件即可。经过我们这几步的定义,以后只需要在模板定义中,不需要缓存的部分,例如,实时比分、广告、时间等,使用{cacheless}{/cacheless}自定义的Smarty块标记,关闭缓存的内容即可。

 

转自:http://www.huachu.com.cn/read/readbookinfo.asp?sectionid=1000001806

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值