phpcms缓存使用总结(memcached、eaccelerator、shm)

来源:www.13sc.com | 游客上传 | 337 次浏览 | 0 条评论

搜索: phpcms 缓存 

这篇文章主要介绍了phpcms中memcached、eaccelerator、shm缓存使用方法,需要的朋友可以参考下

a.模板编译缓存
参考文件include/global.func.php及include/template.func.php
模板编译缓存的原理其实很简单,如果模板是第一次编译,则直接编译它,如果不是第一次编译,则比较模板文件($tplfile)及模板缓存文件 ($compiledtplfile)的修改时间,如果模板文件的修改时间大于编译过的模板缓存文件,则编译模板,否则不编译模板,提高了程序的执行效 率。


复制代码
代码如下:

function template($module = "!!phpcms"!!, $template = "!!index"!!)
{
global $CONFIG;
$compiledtplfile = $CONFIG["!!templatescachedir"!!].$module."!!_"!!.$template."!!.tpl.php"!!;
if($CONFIG["!!templaterefresh"!!])
{
$tplfile = PHPCMS_ROOT."!!/templates/"!!.$CONFIG["!!defaulttemplate"!!]."!!/"!!.$module."!!/"!!.$template."!!.html"!!;
if(!file_exists($compiledtplfile) || @filemtime($tplfile) > @filemtime($compiledtplfile))
{
require_once PHPCMS_ROOT."!!/include/template.func.php"!!;
template_refresh($tplfile, $compiledtplfile);
}
}
return $compiledtplfile;
}

b.在动态页面里面产生静态的缓存文件

与c的缓存原理类似,只是此处生成的文件名相对固定
以问吧模块为例进行说明
用http://www.chf.com/opensource/phpcms2007_sp6_gbk/phpcms/wenba/进行访问
此目录下有个index.php文件,判断当前目录下是否存在名为index_cache.html的文件,如果有没有过失效期,则直接包含此文件,否则动态地读取完数据后保存为index_cache.html文件,以备下次使用。
文件index.php中的内容:


复制代码
代码如下:

<?php
require_once "!!./include/common.inc.php"!!;
$lastedittime = @filemtime("!!index_cache.html"!!);
$lastedittime = $PHP_TIME-$lastedittime;
$autoupdatetime = intval($MOD["!!autoupdate"!!]); //$MOD["!!autoupdate"!!]来自缓存文件data/cache/wenba_setting.php中的内容
if(file_exists("!!index_cache.html"!!) && $lastedittime<$autoupdatetime)
{
echo "include cache file";
include "!!index_cache.html"!!;
}
else
{
echo "read dynamic page";
...
?>

怎么判断文件是否失效呢,文件data/cache/wenba_setting.php中有如下的设置,其中字段autoupdate的值就是文件失效的时间,单位是秒,在后台可以进行设置
文件wenba_setting.php是从哪儿来的呢,进行安装时自动把各种模块的数据保存到数据库中了,安装时就生成缓存数据了,在include/common.inc.php中函数cache_all也可以生成缓存,后台进行设置时cache会自动更新的


复制代码
代码如下:

<?php
return array (
"!!higth_score"!! => "!!100"!!,
"!!anybody_score"!! => "!!2"!!,
"!!answer_give_credit"!! => "!!5"!!,
"!!vote_give_credit"!! => "!!1"!!,
"!!highscore"!! => "!!2"!!,
"!!vote_give_actor"!! => "!!公司白领</p> <p>魔法师</p> <p>科举夺魁</p> <p>武将</p> <p>江湖奇侠"!!,
"!!autoupdate"!! => "!!10"!!,
"!!name"!! => "!!问吧"!!,
"!!moduledir"!! => "!!wenba"!!,
"!!moduledomain"!! => "!!"!!,
"!!linkurl"!! => "!!/opensource/phpcms2007_sp6_gbk/phpcms/wenba/"!!,
);
?>

include/global.func.php
更新模块设置函数


复制代码
代码如下:

function module_setting($module, $setting)
{
global $db,$MODULE,$LANG;
if(!is_array($setting) || !array_key_exists($module,$MODULE)) return FALSE;
if(isset($setting["!!moduledomain"!!]))
{
$moduledomain = $setting["!!moduledomain"!!];
$db->query("UPDATE ".TABLE_MODULE." SET moduledomain="!!$moduledomain"!! WHERE module="!!$module"!!");
unset($setting["!!moduledomain"!!]);
}
$setting = addslashes(serialize(new_stripslashes($setting)));
//将某个模块的多个设置的值经数组序列化以后保存在一个字段setting中
$db->query("UPDATE ".TABLE_MODULE." SET setting="!!$setting"!! WHERE module="!!$module"!!");
cache_module($module);
cache_common();
return TRUE;
}

c.在动态页面里面产生静态的缓存文件

与b的缓存原理类似,只是此处生成的文件名是根据计算$PHP_SELF与$PHP_QUERYSTRING的md5值生成的文件名,相对于所有php动态页面来说都是一样的,这个思想比较精典,值得借签
以问吧模块为例进行说明
文件调用顺序为:index.php -> js.php -> ad.php -> global.func.php
http://www.chf.com/opensource/phpcms2007_sp6_gbk/phpcms/wenba/进行访问
此目录下有个index.php文件,判断当前目录下是否存在名为index_cache.html的文件,如果有,则直接包含此文件,如果不存在此文件,则动态地读取完数据后保存在index_cache.html文件,以备下次使用

用上述的url访问时,页面里面包含有如下的一行js代码
<script language="javascript" src="/opensource/phpcms2007_sp6_gbk/phpcms/data/js.php?id=1"></script>
此js代码其实就是动态调用php页面的内容
http://www.chf.com/opensource/phpcms2007_sp6_gbk/phpcms/data/js.php?id=1

js.php文件的内容:


复制代码
代码如下:

<?php
chdir("!!../ads/"!!);
require "!!./ad.php"!!;
?>

ad.php的内容:


复制代码
代码如下:

<?php
define("!!SHOWJS"!!, 1);
require "!!./include/common.inc.php"!!;
require MOD_ROOT."!!/include/global.func.php"!!;</p> <p>$placeid = intval($id);</p> <p>$query ="SELECT * FROM ".TABLE_ADS." AS a LEFT JOIN ".TABLE_ADS_PLACE." AS p ON (a.placeid=p.placeid) WHERE a.placeid=".$placeid." AND a.fromdate<=UNIX_TIMESTAMP() AND a.todate>=UNIX_TIMESTAMP() AND p.passed=1 AND a.passed=1 AND a.checked=1 ORDER BY a.addtime";
$ads = $db->get_one($query, "CAHCE", 10240);
if(!$ads) exit("!!document.write("")"!!);</p> <p>$db->query("UPDATE ".TABLE_ADS." SET views=views+1 WHERE adsid=".$ads["!!adsid"!!]);</p> <p>$content = ads_content($ads);
$templateid = $ads["!!templateid"!!] ? $ads["!!templateid"!!] : "!!ads"!!;
include template("!!ads"!!, $templateid);
phpcache();
?>

ad.php里面调用了phpcache函数,参考文件include/global.func.php


复制代码
代码如下:

function phpcache($is_js = 0)
{
global $CONFIG,$cachefiledir,$cachefile;
if(!$is_js && $CONFIG["!!phpcache"!!] != "!!2"!!) return FALSE;
$contents = ob_get_clean(); //读取缓冲区里面的内容
if($is_js) $contents = strip_js($contents);
if($CONFIG["!!phpcache"!!] == "!!2"!! && $cachefiledir && $cachefile)
{
dir_create($cachefiledir);
file_put_contents($cachefile, $contents); //在这儿生成一个.html格式的文件,当下次以同样的url访问时,会直接读取缓存了,参见include/common.inc.php中的代码,这儿的代码是非常非常精典的,大家好好借鉴、好好模仿吧
@chmod($cachefile, 0777);
}
/*
向浏览器发送http header,跟浏览器说,此页面不缓存,还告诉浏览器页面的最后修改时间
第一次访问js.php?id=1时向浏览器发送http header,第二次或以后再访问此url时,由于上次已经生成了缓存,所以在include/common.inc.php中直接调用缓存文件了,直到 缓存失效后再次执行此处的动态代码。此处发送的header控制缓存是相对于浏览器来说的;而通过file_put_contents生成的缓存是相对于 电脑硬盘来说的,是不一样的。
*/
header("!!Expires: Mon, 26 Jul 2000 05:00:00 GMT"!!);
header("!!Last-Modified: "!!.gmdate("!!D, d M Y H:i:s"!!)."!! GMT"!!);
header("!!Cache-Control: no-cache, must-revalidate"!!);
header("!!Pragma: no-cache"!!);
echo $contents;
}

上面的phpcache函数中的全局变量$cachefiledir,$cachefile是从哪里来的呢,从这儿来的
文件include/common.inc.php中的内容


复制代码
代码如下:

if(!defined("!!IN_ADMIN"!!))
{
if($CONFIG["!!dbiscache"!!]) $db_file .= "!!_cache"!!;
if($CONFIG["!!phpcache"!!] == "!!2"!!)
{
$cachefileid = md5($PHP_SELF."!!?"!!.$PHP_QUERYSTRING);
$cachefiledir = PHPCMS_ROOT."!!/data/phpcache/"!!.substr($cachefileid, 0, 2)."!!/"!!;
$cachefile = $cachefiledir.$cachefileid."!!.html"!!;
//echo "cachefile:$cachefile";
if(file_exists($cachefile) && ($PHP_TIME < @filemtime($cachefile) + $CONFIG["!!phpcacheexpires"!!]))
{
require $cachefile;
exit;
}
}
if($PHP_QUERYSTRING && preg_match("/^(.*).(htm|html|shtm|shtml)$/", $PHP_QUERYSTRING, $urlvar))
{
parse_str(str_replace(array("!!/"!!, "!!-"!!, "!! "!!), array("!!&"!!, "!!="!!, "!!"!!), $urlvar[1]));
}
}

d.数据库查询结果缓存
下面是include/common.inc.php中的几行代码


复制代码
代码如下:

$db_file = $db_class = "!!db_"!!.$CONFIG["!!database"!!]; //$CONFIG["!!database"!!]位于config.inc.php中,配置可以使用自己的数据库,如mysql,sqlite,sqlserver等
require PHPCMS_ROOT."!!/include/"!!.$db_file."!!.class.php"!!;
$db = new $db_class;
$db->connect($CONFIG["!!dbhost"!!], $CONFIG["!!dbuser"!!], $CONFIG["!!dbpw"!!], $CONFIG["!!dbname"!!], $CONFIG["!!pconnect"!!]);
$db->iscache = $CONFIG["!!dbiscache"!!]; //是否启用 sql cache (只对前台起作用,建议在不生成html并且访问量过大时开启)
$db->expires = $CONFIG["!!dbexpires"!!]; //sql cache 过期时间(秒)

db_mysql_cache.class.php中的代码


复制代码
代码如下:

function query($sql , $type = "!!"!! , $expires = 3600, $dbname = "!!"!!)
{
if($this->isclient)
{
$dbname = $dbname ? $dbname : $this->dbname;
$this->select_db($dbname);
}
/*
$this->iscache表示是否启动了数据库查询缓存
如果启用了数据库查询缓存且$type为CACHE且是select语句,则启用查询缓存
个人感觉这儿$type参数用strtoupper处理一下更好了
*/
if($this->iscache && $type == "!!CACHE"!! && stristr($sql, "!!SELECT"!!))
{
$this->caching = 1; //成员变量caching标识启用了数据库查询缓存,用在下面的fetch_array,num_rows,free_result函数中,其实用iscache就可以判断了,没有必要再用一个成员变量了
$this->expires = $expires; //数据库缓存数据的失效期
return $this->_query_cache($sql); //然后调用_query_cache方法
}
$this->caching = 0;
$func = $type == "!!UNBUFFERED"!! ? "!!mysql_unbuffered_query"!! : "!!mysql_query"!!;
if(!($query = $func($sql , $this->connid)) && $type != "!!SILENT"!!)
{
$this->halt("!!MySQL Query Error"!!, $sql);
}
$this->querynum++;
return $query;
}</p> <p>function _query_cache($sql)
{
$this->cache_id = md5($sql); //计算$sql的md5值,然后作为cache_id
$this->result = array();
$this->cursor = 0;
$this->cache_file = $this->_get_file(); //得到cache文件名
//如果cache数据已经过期,则重新从数据库中取得查询结果,然后保存在数据库中
if($this->_is_expire())
{
$this->result = $this->_get_array($sql); //从数据库中取结果
$this->_save_result(); //保存结果到缓存数据中
}
else
{
$this->result = $this->_get_result(); //缓存没过期直接取缓存数据
}
return $this->result;
}</p> <p> function _get_file()
{
global $CONFIG;
//cache文件的主目录一般是data/dbcache
return $CONFIG["!!dbcachedir"!!].substr($this->cache_id, 0, 2)."!!/"!!.$this->cache_id."!!.php"!!;
}</p> <p>function _is_expire()
{
global $PHP_TIME;
return !file_exists($this->cache_file) || ( $PHP_TIME > @filemtime($this->cache_file) + $this->expires );
}</p> <p>/*
由于方法_get_array只是被方法_query_cache调用,所以在此方法里面直接用函数mysql_unbuffered_query了,因为mysql_unbuffered性能好一点,参考
<a href="http://bbs.chinaunix.net/viewthread.php?tid=958067&extra=page%3D4">http://bbs.chinaunix.net/viewthread.php?tid=958067&extra=page%3D4</a>
*/
function _get_array($sql)
{
$this->cursor = 0;
$arr = array();
$result = mysql_unbuffered_query($sql, $this->connid);
while($row = mysql_fetch_assoc($result))
{
$arr[] = $row;
}
$this->free_result($result);
$this->querynum++;
return $arr;
}</p> <p>function _save_result()
{
if(!is_array($this->result)) return FALSE;
dir_create(dirname($this->cache_file));
file_put_contents($this->cache_file, "<?php return ".var_export($this->result, TRUE)."; ?>");
@chmod($this->cache_file, 0777);
}</p> <p> function _get_result()
{
return include $this->cache_file;
}</p> <p>function fetch_array($query, $result_type = MYSQL_ASSOC)
{
return $this->caching ? $this->_fetch_array($query) : mysql_fetch_array($query, $result_type);
}</p> <p>//从数据库中获取查询的结果
function _fetch_array($result = array())
{
if($result) $this->result = $result;
return isset($this->result[$this->cursor]) ? $this->result[$this->cursor++] : FALSE;
}</p> <p>function num_rows($query)
{
return $this->caching ? $this->_num_rows($query) : mysql_num_rows($query);
}</p> <p>function free_result($query)
{
if($this->caching==1) $this->result = array();
else @mysql_free_result($query);
}

如果把上述的文件存储改为用memcached、eaccelerator、shm等来进行存储的话效率会更高,改动起来也不是太难,后台可以加一个设置选项,如分别是
文件,memcached,eaccelerator,shm等让管理员进行设置,然后调用相应的存储系统进行存储


标签: phpcms 缓存

最热-phpcms

phpcms v9添加热门搜索关键词的方法

PHPCMS V9任意短消息阅读BUG分析与解决方法

PHPcms建站系统-个人建站必不可少的工具

phpcms v9站内外搜索代码分享

Phpcms V9 调用全站最新文章的方法

PHPCMS2008 SP4 心情排行指数不显示的解决办法

PHPCMS 2008 SP3 模板语法规则整理

mysql更改密码后 配置文件应该改的东西 PHPCMS2008&V9

关于phpcms2008 内部递增标变量 $n 使用时的注意事项

PHPCMS V9采集地址中有相对路径的问题及解决方法

FTP二进制形式上传phpcms程序

phpcms2008下的自定义url规则教程

Copyright 2009-2013 13sc.com All Rights Reserved.