你现在的位置:首页 > PHP网站建设知识库 > Discuz > 正文

Discuz缓存原理详解

缓存技术,不管从前还是现在,从来都是被一些cms或其他系统所重视的,从速度,从效率,没有理由不使用缓存。在做discuz二次开发时,我们当然要了解它的缓存原理。

在Discuz里面有一个forumdate文件夹,这个是论坛记录和缓存文件的存放目录,一般这些文件都是自动生成的,我们关心的是其中的缓存文件,在./forumdate/cache/里面存储的都是一些Discuz!的基本设置和一些常量(一般在 $_DCACHE),在./forumdate/template目录下即缓存着已经预编译好的模板文件,想一下,在第一次装上discuz论坛系统打开首页时是不是有类似“缓存文件建立成功,请刷新”的提示,那就是第一次执行缓存动作,生成. /forumdate/template目录下的东西。

在这里,我先大致介绍下流程吧,在用户请求一个页面时,程序会首先到./forumdate/template看一下有没有预编译好的文件,如果有的话,则直接拿来用,如果没有或者缓存过期的话则重新编译,生成文件缓存在./forumdate/template里,想一下phplib模板的处理方式,每次请求页面时都要用正则的方式来匹配模板,而在Discuz!的处理机制中是先用正则匹配模,预编译好放在缓存文件中,每次用户请求页面就直接从缓存中提取,时间,效率自然就来了吧!

看下例如index.php,member.php下面都有个include template(’XXX’);在./include/global.func.php里有template()这个函数,在template函数里又调用到parse_template()这个函数,另外在cache.func.php中还有一个长达1528的程序,这些程序是怎么运转的呢? Discuz的缓存机制是怎样处理每一个细节上的问题的呢?

打开leftmenu.php,为什么拿这个为例子呢,因为它简单明了能说明问题。在最下面有一句include template(’leftmenu’);,刚看到这一句感到很纳闷,include还可以包含一个函数??再打开./include/global.func.php里面的template()这个函数,return $objfile;而在前面有一个$objfile =DISCUZ_ROOT.’./forumdata/templates/’.$templateid.’_’.$file.’.tpl.php’; 这时候才明白,template返回的是这个文件的地址,而这个文件就是上文我们说的“预编译好的文件”,在最后面加上include template(’leftmenu’);,就是为了把这个预编译好的文件包含近来,在leftmenu.php中可以看到在include template(’leftmenu’);之前是没有任何输出的,所有的输出就是$objfile这个文件,那么就按template()这个函数返回的地址找到这个文件,可以看到是一个html夹杂着<? xxx ?>的文件,大家刚学PHP做个留言板或记数器的时候就是写的这样的吧!那为什么最后要的还是这种文件呢?原因很简单—这样做执行速度快而且在前面已经分离了美工和程序!这里和像phplib这种模板引擎的区别在上文也提到了。或许你又会有疑问了,为什么不直接生成静态页面呢,这样做速度不是更快吗?是的,生成静态的是很快,但是你要知道这是一个论坛系统,变化的批频率是相当高的,每次变化都要重新生成静态文件,想一下这是多么大的开销啊!个人认为在一些不是经常变化的CMS或这单存的文章发布系统比较适合生成静态文件。
在template()函数中有这样一段

if($tplrefresh == 1 || ($tplrefresh > 1 && substr($GLOBALS['timestamp'], -1) > $tplrefresh)) {
//如果模板已经修改了,则重新编译
if(@filemtime($tplfile) > @filemtime($objfile)) {
require_once DISCUZ_ROOT.’./include/template.func.php’;
parse_template($file, $templateid, $tpldir);
}
}

$tplrefresh这个变量为模板自动刷新的开关,这段代码的意思是在社会子模板自动刷新的前提下,如果模板文件已经修改了,则重新编译生成缓存文件存在./forumdata/template/下,从这儿也能看到效率…….

在上个代码块中提到parse_template()这个函数,在这里先简单介绍下吧!这个函数是discuz的核心函数,就是用来编译模板文件的,在处理机制上这个函数基本原理和其他的模板类大同小异,用正则对模板进行匹配,不同的是

if(!@$fp = fopen($objfile, ‘w’)) {
dexit(”Directory ‘./forumdata/templates/’ not found or have no access!”);
}
….
….
flock($fp, 2);
fwrite($fp, $template);
fclose($fp);

这段代码的意思就是将编译好的模板文件存到./forumdata/template/下面,关于这个其模板机制也没必要做过多介绍,与本问主题关系不大。