2007/07/25

CIでページキャッシュの拡張

CI付属のキャッシュ機能だとGETパラメータは省いたURLごとにキャッシュをする。
でも実際にはGETのパラメータも含めたURL毎にキャッシュすることが多いいのでコアライブラリを拡張する。拡張方法はCIのドキュメントをみてね。簡単にできますよ。

class MY_Output extends CI_Output {

function MY_Output()
{
parent::CI_Output();
log_message('debug', "MY_Output Class Initialized");
}

function _get_prm() {


if (isset($_GET) && count($_GET) != 0) {
$qryPrm = $_GET;

// IEのキャッシュ対策で時間をパラメーターとして付加している
// その部分のパラメータは考慮しない。「h」がキー
unset($qryPrm["h"]);
ksort($qryPrm);
return $qryPrm;
}
return "";
}

function _concatQryPrm($hm, $emptyExecFlg = true) {

$ret = null;

if ($hm == null || count($hm) == 0) {

return $ret;

}

$keys = array_keys($hm);
for ($cnt = 0; $cnt < count($keys); $cnt++) {

$key = $keys[$cnt];
if ($hm[$key] === null) {
if ($emptyExecFlg == false) {
continue;
}
}

if ($cnt == 0)
$ret .= $key . "=" . $hm[$key];
else
$ret .= "&" . $key . "=" . $hm[$key];

}

return $ret;

}



/**
* Write a Cache File
*
* @access public
* @return void
*/
function _write_cache($output)
{
$CI =& get_instance();
$path = $CI->config->item('cache_path');

$cache_path = ($path == '') ? BASEPATH.'cache/' : $path;

if ( ! is_dir($cache_path) OR ! is_writable($cache_path))
{
return;
}

// $uri = $CI->config->item('base_url').
// $CI->config->item('index_page').
// $CI->uri->uri_string();

// GETパラメータも含める
$q = $this->_concatQryPrm($this->_get_prm());
$q = ($q == "" ? "" : "?" . $q);
$uri = $CI->config->item('base_url').
$CI->config->item('index_page').
$CI->uri->uri_string().
$q;

$cache_path .= md5($uri);

if ( ! $fp = @fopen($cache_path, 'wb'))
{
log_message('error', "Unable to write ache file: ".$cache_path);
return;
}

$expire = time() + ($this->cache_expiration * 60);

flock($fp, LOCK_EX);
fwrite($fp, $expire.'TS--->'.$output);
flock($fp, LOCK_UN);
fclose($fp);
@chmod($cache_path, 0777);

log_message('debug', "Cache file written: ".$cache_path);
}

// --------------------------------------------------------------------

/**
* Update/serve a cached file
*
* @access public
* @return void
*/
function _display_cache(&$CFG, &$RTR)
{
$CFG =& load_class('Config');
$RTR =& load_class('Router');

$cache_path = ($CFG->item('cache_path') == '') ? BASEPATH.'cache/' : $CFG->item('cache_path');

if ( ! is_dir($cache_path) OR ! is_writable($cache_path))
{
return FALSE;
}

// Build the file path. The file name is an MD5 hash of the full URI
// $uri = $CFG->item('base_url').
// $CFG->item('index_page').
// $RTR->uri_string;

// GETパラメータも含める
$q = $this->_concatQryPrm($this->_get_prm());
$q = ($q == "" ? "" : "?" . $q);
$uri = $CFG->item('base_url').
$CFG->item('index_page').
$RTR->uri_string.
$q;

$filepath = $cache_path.md5($uri);

if ( ! @file_exists($filepath))
{
return FALSE;
}

if ( ! $fp = @fopen($filepath, 'rb'))
{
return FALSE;
}

flock($fp, LOCK_SH);

$cache = '';
if (filesize($filepath) > 0)
{
$cache = fread($fp, filesize($filepath));
}

flock($fp, LOCK_UN);
fclose($fp);

// Strip out the embedded timestamp
if ( ! preg_match("/(\d+TS--->)/", $cache, $match))
{
return FALSE;
}

// Has the file expired? If so we'll delete it.
if (time() >= trim(str_replace('TS--->', '', $match['1'])))
{
@unlink($filepath);
log_message('debug', "Cache file has expired. File deleted");
return FALSE;
}

// Display the cache
$this->_display(str_replace($match['0'], '', $cache));
log_message('debug', "Cache file is current. Sending it to browser.");
return TRUE;
}


}

0 件のコメント: