CI緩存機制

今天看下CI的文件緩存機制,使用起來的確很簡單啊。把原理記下來:php

1. 先說下使用方式吧:【這個是直接從手冊,複製過來的】html


啓用緩存功能,只須要將下面的代碼放入你的任何一個控制器(controller)的方法(function)內:緩存

$this->output->cache(n);app

其中n是你但願緩存更新的 分鐘 數。可使用 m/60 來精確到秒,例如 1/60 ,則是精確到 1秒ide

上面的代碼能夠放到任何一個 function 裏面。他的出現順序對緩存並無影響,因此將它放在你認爲最合乎邏輯的地方。一旦上面的代碼放到了控制器的方法中,頁面就會被緩存。codeigniter

警告: 因爲CI存儲緩存文件的方式,只有經過 view 文件的輸出才能被緩存。 優化

注意: 在緩存文件產生以前,請確保application/cache文件夾可寫。 ui

2. 緩存運行原理this

在CI的核心文件 CodeIgniter.php文件182行
url

/*
 * ------------------------------------------------------
 *	Is there a valid cache file? If so, we're done...
 * ------------------------------------------------------
 */
	if ($EXT->call_hook('cache_override') === FALSE
		&& $OUT->_display_cache($CFG, $URI) === TRUE)
	{
		exit;

	}

$EXT->call_hook('cache_override')  調用鉤子,不存在返回false

$OUT->_display_cache($CFG, $URI) 判斷緩存文件當前url下緩存文件是否存在

下面看看output類中 _display_cache方法

/**
	 * Update/serve cached output
	 *
	 * @uses	CI_Config
	 * @uses	CI_URI
	 *
	 * @param	object	&$CFG	CI_Config class instance
	 * @param	object	&$URI	CI_URI class instance
	 * @return	bool	TRUE on success or FALSE on failure
	 */
	public function _display_cache(&$CFG, &$URI)
	{
		$cache_path = ($CFG->item('cache_path') === '') ? APPPATH.'cache/' : $CFG->item('cache_path');

		// Build the file path. The file name is an MD5 hash of the full URI
		$uri =	$CFG->item('base_url').$CFG->item('index_page').$URI->uri_string;
		$filepath = $cache_path.md5($uri);//帶路徑的緩存文件名

		if ( ! @file_exists($filepath) OR ! $fp = @fopen($filepath, FOPEN_READ))
		{
			return FALSE;
		}

		flock($fp, LOCK_SH);

		$cache = (filesize($filepath) > 0) ? fread($fp, filesize($filepath)) : '';

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

		// 檢查序列化文件信息
		if ( ! preg_match('/^(.*)ENDCI--->/', $cache, $match))
		{
			return FALSE;
		}

		$cache_info = unserialize($match[1]);
		$expire = $cache_info['expire'];//緩存的到期時間

		$last_modified = filemtime($cache_path);//取得文件的修改時間

		// 判斷文件是否過時
		if ($_SERVER['REQUEST_TIME'] >= $expire && is_really_writable($cache_path))
		{
			// 若是已到期就刪除
			@unlink($filepath);
			log_message('debug', 'Cache file has expired. File deleted.');
			return FALSE;
		}
		else
		{
			// Or else send the HTTP cache control headers.
			$this->set_cache_header($last_modified, $expire);
		}

		// Add headers from cache file.
		foreach ($cache_info['headers'] as $header)
		{
			$this->set_header($header[0], $header[1]);
		}

		//輸出緩存
		$this->_display(substr($cache, strlen($match[0])));
		log_message('debug', 'Cache file is current. Sending it to browser.');
		return TRUE;
	}

再看看生成文件緩存的方法

/**
	 * Write Cache
	 *
	 * @param	string	$output	Output data to cache
	 * @return	void
	 */
	public function _write_cache($output)
	{
		$CI =& get_instance();
		$path = $CI->config->item('cache_path');
		$cache_path = ($path === '') ? APPPATH.'cache/' : $path;

		if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path))
		{
			log_message('error', 'Unable to write cache file: '.$cache_path);
			return;
		}

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

		$cache_path .= md5($uri);//緩存的文件名就是MD5的當前url值

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

		$expire = time() + ($this->cache_expiration * 60);//緩存時間

		// Put together our serialized info.
		$cache_info = serialize(array(
			'expire'	=> $expire,
			'headers'	=> $this->headers
		));

		if (flock($fp, LOCK_EX))
		{
			fwrite($fp, $cache_info.'ENDCI--->'.$output);//寫入文件
			flock($fp, LOCK_UN);
		}
		else
		{
			log_message('error', 'Unable to secure a file lock for file at: '.$cache_path);
			return;
		}
		fclose($fp);
		@chmod($cache_path, FILE_WRITE_MODE);

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

		// Send HTTP cache-control headers to browser to match file cache settings.
		$this->set_cache_header($_SERVER['REQUEST_TIME'], $expire);
	}

還有緩存刪除_delete_cache這裏就不在粘貼了,詳細看output類吧。

ci文件緩存是很明瞭,就是在載入視圖後,生成一個md5的文件,而後 文件內容中有緩存到期時間,下此從新載入的時候,就可直接調用了

有一個缺點就是全部的緩存文件都放在同一個目錄下,若是站點較大的話,本身能夠修改,分級目錄保存。

下面是CI論壇裏一位牛人  優化緩存機制  擴展了 output類

http://codeigniter.org.cn/forums/forum.php?mod=viewthread&tid=11515

//=================================================================

今天用來CI文件緩存發現分頁的時候不起做用,因而就看緩存的生成方式

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

$CI-uri-uri_string()這個方法不返回帶有查詢查詢字符串的, 因此導致分頁的緩存都是同一個文件名。的分頁url後面是 ?page=&name=&是這種形式的  我把上述中的url改了一下

$uri =	$CI->config->item('base_url').
				$CI->config->item('index_page').
				$CI->input->server('REQUEST_URI');

搞定。

相關文章
相關標籤/搜索