Concrete5 (5.7) - Don't cache page or current block on block error

♀尐吖头ヾ 提交于 2019-12-14 03:59:01

问题


I've got a block that relies on a fairly flaky third party service to get data to render so, when it does encounter a problem, I'd like to display an error message, rather than throw an exception and not render the page.

Easy enough to do until you come to block/page caching. The data has a long lifetime so, when found, it's fine to cache everything. When it isn't, though, the page is cached with the error message in place. As such, I need to tell the CMS not to save the block or page output to the cache.

Example code (within block controller):

public function view() {
    try {
        $this->set ('data', $this->getData());

    } catch (\Exception $e) {
        \Log::addError ('Blockname Error: '.$e->getMessage(), [$e]);
        $this->render ('error');
    }
}

Within the catch block I've tried both $this->btCacheBlockOutput = true; and \Cache::disableAll(); but neither works. Is there a way to tell C5 not to cache anything on the current request?


回答1:


The BlockController in the concrete folder has these protected variables set as standard :

protected $btCacheBlockRecord = true;
protected $btCacheBlockOutput = false;
protected $btCacheBlockOutputOnPost = false;
protected $btCacheBlockOutputForRegisteredUsers = false;

So if you set all these on your block controller.php on false, it should not cache your block.

class Controller extends BlockController
{
  protected $btCacheBlockRecord = false;
  protected $btCacheBlockOutput = false;
  protected $btCacheBlockOutputOnPost = false;
  protected $btCacheBlockOutputForRegisteredUsers = false;
  public function view(){
    .....

This will disable the caching of the block (even if the third party connection succeeds).

A different solution is to save the data received from the third party in the database (for example as a json string) and load the data from the database if the third party connection fails... if the third party connection succeeds, you can update the record in the database.

Depending of the answer of the third party service you can set the conditions. Example:

//service returns on OK:
//array('status' => 'ok')
//service returns on NOT OK:
//array('status' => 'nok')

public function view() {
    $data = $this->getData();
    if($data['status'] == 'ok'){
       //save data to database in a config value using concrete Config class
       $configDatabase = \Core::make('config/database');
       $configDatabase->save('thirdpartyanswer', $data);
       $this->set('data', $data);
    }else{
       //getData function returned error or nok status
       //get data from concrete Config class
       $configDatabase = \Core::make('config/database');
       if($configDatabase->get('thirdpartyanswer')) != ''){
          //set data as "old" data from config
          $this->set('data', $configDatabase->get('thirdpartyanswer'));
       }else{
          //no data in config -> set error and nothing else
          $this->set('error', 'An error occured contacting the third party');
       }
    }
}

(The code above has not been tested)
More information on storing config values :
https://documentation.concrete5.org/developers/packages/storing-configuration-values

* Edit *

A third option is to purge the cache for that specific page if the call fails.

At the top of your blockcontroller :

use \Concrete\Core\Cache\Page\PageCache;
use Page;

In the 'if' when the call to the API fails :

$currentPage = Page::getCurrentPage();
$cache = PageCache::getLibrary();
$cache->purge($currentPage);

Found at : https://www.concrete5.org/community/forums/5-7-discussion/programmatically-expiring-pages-from-cache



来源:https://stackoverflow.com/questions/42010269/concrete5-5-7-dont-cache-page-or-current-block-on-block-error

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!