2012-03-16 44 views
9

我有一个关于视图缓存和浏览器缓存在CakePHP 2.1中一起工作的问题。CakePHP 2.1:浏览器缓存vs查看缓存

我刚刚升级我的应用程序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的是否有被是否返回缓存的页面副本)。

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

回答

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库进行一些深层修改。

+1

是的,由Controller动作对Response对象所做的任何修改都不会被缓存,这包括Cache控制头的设置。有一个关于此的开放票(虽然没有与缓存相关):http://cakephp.lighthouseapp.com/projects/42648/tickets/2358-cachehelper-defect-with-response 唯一建议的解决方法是手动设置标题布局或'Controller :: beforeFilter()'(启用回调)。 – pixelistik 2012-06-24 14:21:51