使用Zend_Cache_Backend_Static时防止错误页面缓存

时间:2012-04-19 12:47:13

标签: php zend-framework

我们目前正在运行一个使用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);

它很好用,但我不想首先写这个页面!

3 个答案:

答案 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。

相关问题