标题 | 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, "<?phpn return ".var_export($this->result, TRUE).";n?>"); @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等让管理员进行设置,然后调用相应的存储系统进行存储 |
随便看 |
|
在线学习网考试资料包含高考、自考、专升本考试、人事考试、公务员考试、大学生村官考试、特岗教师招聘考试、事业单位招聘考试、企业人才招聘、银行招聘、教师招聘、农村信用社招聘、各类资格证书考试等各类考试资料。