织梦静态模板引擎检测模板缓存LoadCache($filename)

admin2020-01-141135

这个函数的功能是在载入模板的时候,要检测一下这个模板有没有缓存文件,若有说明这个模板已经解析过了,就不用解析了,反之,则要重新解析,这个是在载入模板的时候调用的一个函数,刚开始的时候自认为检测模板函数,直接检测一下在data/tplcachde/里面是不是存在这个模板的缓存文件名,不就可以了吗?但是,当读了一下这个函数的代码才知道,原来并没有我们想像的那么简单,这也告诉我们对于研究织梦函数的重要性,如果你研究函数多了,你会发现自己的思考问题会越来越全面,这样不管以后我们做织梦二次开发,还是自己开发一个系统,那么,一定会有很大帮助的。在分析函数的过程中,我们的思维不断的变强大,建议大家平常多分析一些函数,最好像我这样做出教程来,这样你会发现自己不知不觉中你也会写函数了。

这个函数所在文件:/include/dedetag.class.php

代码分析开始:

1.若不缓存文件,则直接返回false,如果你的系统设置连缓存文件都不缓存的话,那么,就没有必要检测了,所以,这一点要考虑。代码如下:

        if(!$this->IsCache)
        {
            return FALSE;
        }

2.对模板以及缓存文件作初始化处理,然后,判断缓存文件是否存在,代码如下:

        $cdir = dirname($filename);
        $cachedir = DEDEROOT.$cfg_tplcache_dir;
        $ckfile = str_replace($cdir,'',$filename).substr(md5($filename),0,16).'.inc';
        $ckfullfile = $cachedir.'/'.$ckfile;
        $ckfullfile_t = $cachedir.'/'.$ckfile.'.txt';
        $this->CacheFile = $ckfullfile;
        $this->TempMkTime = filemtime($filename);
        if(!file_exists($ckfullfile)||!file_exists($ckfullfile_t))
        {
            return FALSE;
        }

若系统设置缓存,那么,我们就根据模板进行缓存名的查找并判断。dirname($filename) 就是获得除了模板名外的模板路径,例如,模板路径为:www.dedebae.com/dede/templets/index.htm ,那么,经过dirname('www.dedebae.com/dede/templets/index.htm')后,就得到了www.dedebase.com/dede/templets

我做了个测试,在test.php文件写入如下代码:

<?php

$c="www.dedebae.com/dede/templets/index.htm";

echo dirname($c);

?>

显示的结果如下图所示。

然后,定义缓存路径:$cachedir = DEDEROOT.$cfg_tplcache_dir;也就是$cachedir=/data/tplcache/ 这是织梦系统默认的缓存路径,如果你没有改的话,一般我们也不会改这个,因为,改了没有什么意义。

定义缓存文件名:str_replace($cdir,'',$filename).substr(md5($filename),0,16).'.inc';先把模板路径里面的前面路径都去掉,这样就得到了模板文件名index.htm,然后,再加md5加密后,取前16位,这样我们就得到了index.htmxxx.inc文件了,例如 index.htmab3648abc957b491.inc。

组装缓存文件完整路径:$ckfullfile = /data/tplcache/index.htmab3648abc957b491.inc

组装解析模反后的时间txt文件:也就是在上面的路径后面加个后缀$ckfullfile_t = /data/tplcache/index.htmab3648abc957b491.inc.txt 这个文件里面存放的是缓存文件时间。所以,在解析文件时这二个一起生成的。

$this->CacheFile = $ckfullfile;
$this->TempMkTime = filemtime($filename);

这二行分别是设置缓存文件,然后,把模板修改时间放在$this->TempMKTime里面。

以上做的全都是为下面这个判断准备的,判断上面的缓存文件是不是已经存在且缓存时间是不是已经存在,若二者同时存在,则说明模板已经缓存了,若其中任何一个不存在,则表示没有缓存过这个模板解析后的缓存文件,返回flase。

若缓存过了应当返回true 这是我们一般人这样想的,既然,都有这个缓存文件和缓存时间了,说明模板已经缓存了,应当返回true,但是,这样做不够好,如果缓存文件里面是空的,或是里面有问题呢?那模板一样解析不出来,所以,这样考虑不够周全,这也是我分析这个函数的一个重要原因,特别是编写程人员,考虑全面是基本的素养。

3.检测模板最后更新时间: 如果这个缓存文件存在,而模板更新了,这时模板里面的内容可能更新了,这时这个缓存文件可能跟我们更新后的模板的缓存文件不一样,也就是我们的模板有可能增减模板内容,这时就中重新缓存,所以,这是里要检测一下模板缓存时间和模板更新时间是不是相等,若不相等,则返回false,返回false就说明要重新缓存解析后的模板。

代码如下:

        $fp = fopen($ckfullfile_t,'r');
        $time_info = trim(fgets($fp,64));
        fclose($fp);
        if($time_info != $this->TempMkTime)
        {
            return FALSE;
        }

4.若代码能执行到第四步,说明缓存文件已经存在,且,上面的几种情况都不会出现,也就是缓存文件正常,这时就要分析一下缓存文件内容了,如果缓存文件内容正常,那么,说明缓存文件才是真正的缓存文件,也就不要去再缓存一次解析后的模板了,这样可以减轻服务器压力,特别是对于大型网站来说。

要分析这个缓存文件首先得引入进这个函数里面include($this->CacheFile);然后,对里面的内容进行分析。

这个缓存文件里面存放的是一个数组$z 这是一个二维数组,存放是模板里面的标签,标签属性和值,这个$z的数组格式如下:

$z=array("标记","底层模板","标签开始位置","标签的结束位置",array('name'=>'变量名'))

$z=array("标记","底层模板","标签开始位置","标签的结束位置",array('属性名'=>'属性值','属性名'=>'属性值','属性名'=>'属性值','属性名'=>'属性值'......))

当然,第一个数组时面的并不一定是name,也有可能是filename等,要看具体的标签了。具体数组如下所示,我只截取有代表性的几个:

$z[1]=Array("global","",277,303);
$z[1][4]['name']="cfg_webname";

$z[11]=Array("include","",2275,2310);
$z[11][4]['filename']="head.htm";

$z[12]=Array("arclist","\r\n    <h2><a href=\"[field:arcurl/]\">[field:title/]</a></h2>\r\n    <p>[field:info/]...<a href=\"[field:arcurl/]\">[查看全文]</a></p>\r\n    ",2455,2653);
$z[12][4]['flag']="h";
$z[12][4]['limit']="0,1";
$z[12][4]['infolen']="230";

这些就是模反缓存里面的内容。 

下面这段代码就是:把缓冲数组内容读入类

  if( isset($z) && is_array($z) )
        {
            foreach($z as $k=>$v)
            {
                $this->Count++;
                $ctag = new DedeTAg();
                $ctag->CAttribute = new DedeAttribute();
                $ctag->IsReplace = FALSE;
                $ctag->TagName = $v[0];
                $ctag->InnerText = $v[1];
                $ctag->StartPos = $v[2];
                $ctag->EndPos = $v[3];
                $ctag->TagValue = '';
                $ctag->TagID = $k;
                if(isset($v[4]) && is_array($v[4]))
                {
                    $i = 0;
                    foreach($v[4] as $k=>$v)
                    {
                        $ctag->CAttribute->Count++;
                        $ctag->CAttribute->Items[$k]=$v;
                    }
                }
                $this->CTags[$this->Count] = $ctag;
            }
        }

如果按照上面的缓存文件内容,进行分析这段就简单了,就是实例化了二个类,然后,把缓存文件里面的内容存入标签数组里面,上面这段对应的$this->Ctags值类似如下所示:

[code]DedeTag Object
(
    [IsReplace] =>
    [TagName] => lh
    [InnerText] =>

    [StartPos] => 755
    [EndPos] => 870
    [CAttribute] => DedeAttribute Object
        (
            [Count] => 7
            [Items] => Array
                        (
                                    [tagname] => lh
                                     [itemname] => 楼号
                                     [autofield] => 1
                                     [type] => text
                                      [isnull] => true
                                      [default] =>
                                      [maxlength] => 250
                                      =>
                                    )

        )

    [TagValue] =>
    [TagID] => 6
)[/code]

若$z 不是一个数组并且没有设置,那么,说明这这个模板的没有缓冲数组,那么,直接把标记集合$this->CTags置为空,也就没有标记。但不管有没有缓冲数组$z都表示这个有这个缓存文件了,最后,返回truue 。

网友评论