9

我对 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 视图缓存似乎会覆盖浏览器缓存(具体来说,Last-Modified当页面从 CakePHP 视图缓存提供时,不会发送任何标题)。这会阻止浏览器缓存从 CakePHP 的视图缓存提供的页面。

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

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

4

1 回答 1

2

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

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

于 2012-05-10T04:12:16.217 回答