CakePHP 2.1:浏览器缓存与View缓存

时间:2012-03-16 14:58:20

标签: cakephp caching http-headers cakephp-2.1

我对CakePHP 2.1中视图缓存和浏览器缓存的工作方式有疑问。

我刚刚将我的应用程序升级到CakePHP 2.1,并使用新的$this->response->modified方法设置了HTTP缓存(效果很好):

class ArticlesController extends AppController {
    public function view($id) {
        $article = $this->Article->find(
            'first',
            array('conditions' => array('Article.id' => $id))
        );

        $this->response->modified($article['Article']['modified']);

        $this->set(compact('article'));
    }
}

我还设置了CakePHP视图缓存:

class ArticlesController extends AppController {
    public $cacheAction = array(
        'view' => array('callbacks' => true, 'duration' => "1 week"),
    }
}

独立使用时效果都很好。但是,当两者都启用时,CakePHP视图缓存似乎会覆盖浏览器缓存(具体来说,当从CakePHP视图缓存提供页面时,不会发送Last-Modified标头)。这会阻止浏览器缓存从CakePHP的视图缓存中提供的页面。

理想情况下,我希望浏览器缓存页面,即使它们是从CakePHP的缓存中提供的(即我希望CakePHP返回Last-Modified标头,并响应浏览器的If-Modified-Since请求标头,无论CakePHP是否返回页面的缓存副本)。

我只是想知道这是否是预期的行为,是否我做错了什么,或者是否是没有考虑过(或者认为不重要)的事情。

1 个答案:

答案 0 :(得分:2)

查看缓存本质上并不是在每个请求上实际执行控制器的方法。我猜它会执行一次操作,然后将输出缓存到磁盘(或者,您正在使用的任何缓存引擎)。如果您look at the CacheHelper's _writeFile method,您可以看到如何构建缓存视图。

    $file = '<!--cachetime:' . $cacheTime . '--><?php';

    if (empty($this->_View->plugin)) {
        $file .= "
        App::uses('{$this->_View->name}Controller', 'Controller');
        ";
    } else {
        $file .= "
        App::uses('{$this->_View->plugin}AppController', '{$this->_View->plugin}.Controller');
        App::uses('{$this->_View->name}Controller', '{$this->_View->plugin}.Controller');
        ";
    }

    $file .= '
            $request = unserialize(\'' . str_replace("'", "\\'", serialize($this->request)) . '\');
            $response = new CakeResponse(array("charset" => Configure::read("App.encoding")));
            $controller = new ' . $this->_View->name . 'Controller($request, $response);
            $controller->plugin = $this->plugin = \'' . $this->_View->plugin . '\';
            $controller->helpers = $this->helpers = unserialize(base64_decode(\'' . base64_encode(serialize($this->_View->helpers)) . '\'));
            $controller->layout = $this->layout = \'' . $this->_View->layout . '\';
            $controller->theme = $this->theme = \'' . $this->_View->theme . '\';
            $controller->viewVars = unserialize(base64_decode(\'' . base64_encode(serialize($this->_View->viewVars)) . '\'));
            Router::setRequestInfo($controller->request);
            $this->request = $request;';

    if ($useCallbacks == true) {
        $file .= '
            $controller->constructClasses();
            $controller->startupProcess();';
    }

    $file .= '
            $this->viewVars = $controller->viewVars;
            $this->loadHelpers();
            extract($this->viewVars, EXTR_SKIP);
    ?>';

它创建一个新的Controller对象(带有一个新的CakeResponse)并加载可能在视图中使用的所有帮助程序,插件等,并将其写入缓存。

似乎将Last-Modified标头添加到缓存操作/视图的响应中可能需要对核心CakePHP库进行一些深层修改。