Reputation: 269
Greetings,
I'm writing a CI web application which implements the standard file caching functionality as such:
$this->output->cache(n);
I'm using a combination of segments and query string parameters, and appear to be experiencing an issue as a result. What I'm seeing in my use cases and in the Output class code is that the caching is solely segment based. As such, http://www.example.com/segment/?q=foo and http://www.example.com/segment/?q=bar are treated as identical requests.
Does anyone have any insight or recommendations regarding how the url_helper, Output class, or CI base class can be edited such that the above example treats example.com/segment/?q=foo and example.com/segment/?q=bar as separate, unique requests and stores the responses in separate files individually?
Upvotes: 5
Views: 2765
Reputation: 4775
Due to this is very old answer and the website that was linked to does not exist anymore (new link). I'll copy the code to here for old version of Codeigniter.
This is an answer since Codeigniter 2.
Create MY_Output.php file in application/core and use the code below.
<?php
/**
* @author vee
*/
class MY_Output extends CI_Output
{
public function __construct()
{
parent::__construct();
}// __construct
/**
* Update/serve a cached file
*
* @access public
* @return void
*/
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;
// buld query strings
$querystrings = $_SERVER['QUERY_STRING'];
if ( $querystrings != null ) {$querystrings = "?".$querystrings;}
$uri = $uri.$querystrings;
$filepath = $cache_path.md5($uri);
if ( ! @file_exists($filepath))
{
return FALSE;
}
if ( ! $fp = @fopen($filepath, FOPEN_READ))
{
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'])))
{
if (is_really_writable($cache_path))
{
@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;
}// _display_cache
/**
* Write a Cache File
*
* @access public
* @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();
// buld query strings
$querystrings = $_SERVER['QUERY_STRING'];
if ( $querystrings != null ) {$querystrings = "?".$querystrings;}
$uri = $uri.$querystrings;
$cache_path .= md5($uri);
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);
if (flock($fp, LOCK_EX))
{
fwrite($fp, $expire.'TS--->'.$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);
}// _write_cache
}
Clear all cache files and folders in application/cache.
this can fix codeigniter cache with querystring codeigniter cache with querystring
it is thai language page but you can just copy that code and put it in application/core/MY_Output.php :)
Upvotes: 4
Reputation: 1840
Into config/config.php
You should enable cache_query_string like this
$config['cache_query_string'] = TRUE;
take all query parameters into account. Please be aware that this may result in numerous cache files generated for the same page over and over again.
Upvotes: 3
Reputation: 41
Here's some code to override Codeigniter's Output class which seems to work for me.
Create the file application/core/MY_Output.php, copy in the _write_cache() and _display_cache() functions from Output.php and update it like this:
class MY_Output extends CI_Output {
function __construct() {
parent::__construct();
}
function _write_cache($output) {
....
$uri = $CI->config->item('base_url').
$CI->config->item('index_page').
$CI->uri->uri_string();
// append querystring
$qs = (empty($_SERVER['QUERY_STRING'])) ? '' : '?'.$_SERVER['QUERY_STRING'];
$uri .= $qs;
// append querystring
....
}
function _display_cache(&$CFG, &$URI)
....
$uri = $CI->config->item('base_url').
$CI->config->item('index_page').
$URI->uri_string;
// append querystring
$qs = (empty($_SERVER['QUERY_STRING'])) ? '' : '?'.$_SERVER['QUERY_STRING'];
$uri .= $qs;
// append querystring
....
}
Upvotes: 1
Reputation: 4200
You should cache if the value of _GET is empty
if(!$_GET)
$this->output->cache(0);
Upvotes: -1