我们目前正在运行一个使用Zend_Cache_Backend_Static将页面缓存到静态html文件的应用程序。这非常有效,除了我们的缓存在请求不正确的URL时充满了数百个空文件和文件夹。如果抛出异常,有没有办法阻止页面被缓存?我惊讶地发现这不是标准行为。
我已经做了一点挖掘,实际上处理保存静态html页面的ZF代码如下所示:Zend_Cache_Frontend_Capture:
public function _flush($data) {
$id = array_pop($this->_idStack);
if ($id === null) {
Zend_Cache::throwException('use of _flush() without a start()');
}
if ($this->_extension) {
$this->save(serialize(array($data, $this->_extension)), $id, $this->_tags);
} else {
$this->save($data, $id, $this->_tags);
}
return $data;
}
此函数是ob_start的output_callback。我已经尝试抓住响应对象来测试状态,但它似乎不能在_flush中工作。
$response = Zend_Controller_Front::getInstance()->getResponse();
if($response->getStatus() == '200') {
// do the save as normal
}
else {
// do nothing
return false;
}
我唯一的另一个想法是测试$ data的长度,只有缓存,如果strlen($ data)> 0似乎有用,但感觉不够健壮。
更新
不幸的是,当我们点击ErrorController时,静态页面已经被写入缓存,因此在那时禁用缓存将不起作用。但是,可以基于$ _SERVER ['REQUEST_URI']删除页面,这是首次写入页面时用作id的内容。这行可以添加到ErrorController中的errorAction的开头:
$this->_helper->cache->removePage($_SERVER['REQUEST_URI'], true);
它很好用,但我不想首先写这个页面!
答案 0 :(得分:2)
从进一步的实验中,问题不在于导致404s的标准Zend Framework异常(即Zend_Controller_Plugin_ErrorHandler :: EXCEPTION_NO_ROUTE,Zend_Controller_Plugin_ErrorHandler :: EXCEPTION_NO_CONTROLLER,Zend_Controller_Plugin_ErrorHandler :: EXCEPTION_NO_ACTION),而是我的自定义异常。现在我很清楚这一点,因为Zend_Cache_Backend_Static需要在动作控制器的init方法中初始化。任何没有路线,控制器或行动的情况,无论如何都不会被初始化。
我在用户可能正在查询不存在的文章的现有操作中抛出异常。因此,在init中启用了缓存,并且在我们在前端控制器插件中点击postDispatch的时候写了页面(仍然不确定为什么会出现这种情况)所以我不能在那时取消。然后,一种解决方案是在抛出异常时取消缓存。管理静态页面缓存的标准方法是使用Zend_Controller_Action_Helper_Cache操作助手。我已将此扩展为添加取消方法,如下所示:
<?php
class Zend_Controller_Action_Helper_PageCache extends Zend_Controller_Action_Helper_Cache {
public function cancel() {
$cache = $this->getCache(Zend_Cache_Manager::PAGECACHE);
$cache->setOption('caching', false);
$cache->getBackend('disable_caching', true);
}
}
我的动作控制器现在看起来像这样:
<?php
class IndexController extends Zend_Controller_Action {
private $_model;
public function init() {
$this->_model = new Model();
// using extended pageCache rather than $this->_helper->cache:
$this->_helper->pageCache(array('index'), array('indexaction'));
}
public function indexAction() {
$alias = $this->_request->getParam('article');
$article = $this->_model->getArticleByAlias($alias);
if(!$article) {
// new cancel method will disable caching
$this->_helper->pageCache->cancel();
throw new Zend_Controller_Action_Exception('Invalid article alias', 404);
}
$this->view->article = $article;
}
}
答案 1 :(得分:0)
您应该更改.htaccess文件RewriteRules以使用选项-s检查文件大小
这样,如果在缓存页面时发生错误(从而生成0字节文件),则不会永久存储在缓存中。
答案 2 :(得分:-1)
如果您使用标准ErrorController
来处理404,500和未处理的异常,并且可以从那里获得对缓存对象的引用,则可以从错误处理程序中禁用缓存。
在错误控制器中(或者您想从中取消缓存的任何地方),请尝试:
$cache->setOption('caching', false);
当save()
调用Zend_Cache_Core
的{{1}}元时,会看到Zend_Cache_Frontend_Capture::_flush()
选项设置为false,并且实际上不会将数据保存到缓存并返回true。