2012-04-19 85 views
1

我们目前正在运行一个应用程序,它使用Zend_Cache_Backend_Static将页面缓存到静态html文件。这工作得很好,除了当请求不正确的URL时,我们的缓存中充满了数百个空文件和文件夹。如果抛出异常,有什么办法可以防止页面被缓存?我很惊讶地发现这不是标准行为。使用Zend_Cache_Backend_Static防止错误页面缓存

我做了一个小挖和实际上拯救了静态的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; 
} 

我唯一想到其他是测试的$长度数据,只有当strlen的($数据)缓存> 0似乎工作,但感觉并不足够强大。

更新:

不幸被我们打的ErrorController静态页面已经被写入到缓存中,因此,禁用该点的缓存将无法正常工作的时间。但是,可以根据$ _SERVER ['REQUEST_URI']删除页面,这是在第一次写入页面时用作ID的页面。这条线可以添加到errorAction开始在ErrorController:

$this->_helper->cache->removePage($_SERVER['REQUEST_URI'], true); 

它工作得很好,但我不希望写入页摆在首位!

回答

-1

如果您使用标准ErrorController来处理404,500和未处理的异常,并且您可以从中获取对缓存对象的引用,则可以禁用错误处理程序的缓存。

在您的错误控制器(或任何你想取消从高速缓存),尝试:

$cache->setOption('caching', false); 

Zend_Cache_Coresave()梅托德由Zend_Cache_Frontend_Capture::_flush()调用时,它会看到caching选项设置为false并且它实际上不会将数据保存到缓存并返回true。

+0

当我们点击ErrorController时,静态页面已经被写入,所以这没有效果。 – baseten 2012-04-20 09:51:48

+0

在这种情况下,运行'routeShutdown()'的插件可能会足够早以禁用高速缓存,但当时您应该知道该页面是404。 – drew010 2012-04-20 17:13:23

+0

好主意。我会给它一个去... – baseten 2012-04-23 14:57:01

2

从进一步的实验问题不下来到标准Zend框架的异常导致404(即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中启用了缓存,并且在我们点击Front Controller插件中的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; 
    } 
} 
0

你应该改变你的.htaccess文件的RewriteRules检查与选项的filesizes - s

这样,如果在缓存页面时发生错误(因此生成0字节文件),它将不会永久存储在缓存中。