Codeigniter在处理查询字符串参数时的缓存问题

5

你好,

我正在编写一个CI Web应用程序,实现标准文件缓存功能如下:

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

我正在使用片段和查询字符串参数的组合,但似乎出现了问题。在我的用例和Output类代码中看到的是缓存仅基于片段。因此,http://www.example.com/segment/?q=foohttp://www.example.com/segment/?q=bar 被视为相同的请求。
有没有人对如何编辑url_helper、Output类或CI基类以使上述示例将 example.com/segment/?q=fooexample.com/segment/?q=bar 视为单独的、独特的请求并将响应分别存储在不同的文件中有任何见解或建议?

可能是Codeigniter带有GET参数的页面缓存的重复问题。 - Seb33300
4个回答

4

由于这是一个很老的答案,链接到的网站不再存在(新链接)。我会将代码复制到这里供Codeigniter旧版本使用。

自Codeigniter 2以来就有了这个答案。

application/core中创建MY_Output.php文件,并使用下面的代码。

<?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


}

清除 application/cache 中的所有缓存文件和文件夹。

原始答案(2011年)

这可以修复带查询字符串的 CodeIgniter 缓存。 CodeIgniter 缓存带查询字符串

这是泰语页面,但您可以将该代码复制并放入 application/core/MY_Output.php 文件中 :)


3

进入config/config.php文件

您应该这样启用cache_query_string功能

$config['cache_query_string'] = TRUE;

考虑所有查询参数。 请注意,这可能会导致为同一页面生成大量的缓存文件。


1

这里有一些代码,可以覆盖Codeigniter的Output类,对我来说似乎很有效。

创建文件application/core/MY_Output.php,从Output.php中复制_write_cache()和_display_cache()函数,并进行以下更新:

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

        ....
    }

-1

如果_GET的值为空,您应该进行缓存

if(!$_GET)
    $this->output->cache(0);

Chumillas,这并没有回答问题。如果我传达问题存在误解,我很抱歉。我希望查询字符串作为与缓存相关的信息提供服务。 - wannabenerd
这并不像它所暗示的那样起作用。一旦被缓存(在这种情况下,如果页面没有查询字符串加载),所有控制器逻辑都将被绕过,因此缓存页面将被显示,而不管这行代码如何。此外,这只是禁用缓存,而不是解决方案。 - Thor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接