Page And Block Caching

I had an issue the other day born out of a misconception about the way block and page caching works. I created a Known User Role module, which includes a block saying something like "Welcome back, !username" to so-called "known" users. I created it on my development Drupal site with caching Disabled (at admin/settings/performance) and it worked great. I implemented this in hook_block(), which I presumed would exclude this dynamic block from all caches:

<?php
 
if ($op == 'list') {
   
$blocks[0]['info'] = t('Known user login');
   
$blocks[0]['cache'] = BLOCK_NO_CACHE;
    return
$blocks;
  }
?>

However, with Drupal caching set to Normal I was experiencing caching problems, in spite of the BLOCK_NO_CACHE line (anonymous users would be welcomed back as though they were someone else). This is because there is a fundamental difference between block and page caching - while there are some simple caching choices you can make from the block module as to how and when blocks are cached in the page cache, the page cache itself has utterly no awareness of the block cache. It is quite "stupid", for want of a better word. It saves a simple snapshot of the current page to be shown to anonymous users later.

If page cache is enabled then blocks *will* be cached, regardless of block cache settings in hook_block(). The PHP above simply means if page caching is disabled the block caching engine will not cache that block. There is absolutely nothing you can do to exclude a block from the page cache. It fundamentally does not work like that.

I am currently debating the idea of getting around this by offering the option in admin of clearing the cache on page load for known user, so site admins who don't mind the performance hit can still use the feature. It's more of a problem for projects like Ecommerce and Ubercart, who might want to show a dynamic shopping basket for anonymous users. This sort of thing won't work. =(

7 comments

by phr3ak on Thu, 22/10/2009 - 17:54

Are all blocks cached when page cache is enabled?

by greg.harvey on Thu, 22/10/2009 - 18:00

Yes!

by Jamie Giberti on Tue, 19/01/2010 - 09:34

Hi Greg,

(think I follow you on Twitter!), Do you know if this is still the case? This seems bloody stupid to me for lack of a better way to describe it.

Cheers

Jamie

by greg.harvey on Tue, 19/01/2010 - 10:02

'Fraid so... It is still the case. The only way around it I know of is not for the feint-hearted: Panels! It's the only system I'm aware of in Drupal that allows caching per page element.

Also, there's this bug to be aware of:
http://drupal.org/node/618864

by gib123 on Mon, 24/05/2010 - 07:35

just to add to this, you can use views caching too... and the block cache alter module... and the tough way isn't too bad, you got to manually update the cache each time - and you can refer the block cache alter module :)

by d.neivan on Tue, 21/12/2010 - 15:39

Found a solution for the problem:

just download this module Block Tools

and write in your template.php nearly following:

function YOURTHEME_preprocess_block(&$vars, $hook) {
  if ($vars['block']->module == 'YOURMODULE' && $vars['block']->delta == BLOCKDELTA) {
    $vars['block']->content = blocktools_get_block_content('YOURMODULE', $vars['block']->delta, TRUE);
    $vars['content'] = $vars['block']->content;
  }
}

by JirkaRybka on Thu, 23/12/2010 - 12:52

Page caching only works for anonymous users, while block cache helps performance for authenticated users. Usually blocks change per-role, per-page or so, which doesn't interfere with page caching - page cache is in fact per-page AND per-role (i.e. anonymous only). So it's not so much stupid, and on hight traffic sites it's absolutely necessary to even survive the load, I assure you. Blocks with dynamic content (not per-page, per-role, or so) are rare, and also the cache is flushed on each new post being saved, and each time cron runs.

You can flush the cache when your contents changed, with cache_clear_all(), or you can prevent the page from being cached by setting a message drupal_set_message(), by having POST form data etc. - however, this should be rare, to keep the benefits of caching.

Post new comment

Filtered HTML

  • Allowed HTML tags: <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <blockquote>
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
  • To post pieces of code, surround them with <code>...</code> tags. For PHP code, you can use <?php ... ?>, which will also colour it based on syntax.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
By submitting this form, you accept the Mollom privacy policy.
© 2010 Greg Harvey. Drupal theme by Kiwi Themes.