Block caching with pagers

Drupal 6 and future core versions come with block caching. There are several constants you can set to determine how it is cached from none to per page, per role etc which then can hugely improve the performance on your site for both anonymous and authenticated users. But the cache also needs to be rebuild when there has been a total wipe of the page and block cache. Per page caching is an interesting one, but in some use cases leads to a lot of entries which you sometimes don't need.

An example: with faceted search (either with Apache Solr or with the Faceted search module), you can put a block in a sidebar giving you a list of facets to browse through results. Setting caching per page makes sense because the block contents will change depending on the facet you have clicked on. However, what with pagers ? The block will always have the same facet list, but will have a cache entry for each block because request_uri() will be different. We can avoid that one by having our own logic in a custom block.

This implementation exposes a new block and we deliberately set the cache to BLOCK_NO_CACHE because we will do our own logic in the function that will return the content of the block.

<?php
/**
* Implementation of hook_block().
*/
function test_block($op = 'list', $delta = 0, $edit = array()) {
  if (
$op == 'list') {
    return array(
     
0 => array(
       
'info' => 'Block cache per page with pager',
       
'cache' => BLOCK_NO_CACHE,
      ),
    );
  }
  elseif (
$op == 'view' && $delta == 0) {
    return
test_block_view();
  }
}
?>

The function that returns the content will use request_uri() and parse_url() to get the path that's requested and we will use that path as our own cache_id. We simply ignore all queries that might be available in the URI because we know that the block may have the same content for every page, despite any queries. This is a simple example, but you can add more logic depending on your use case of course. We store our entries in the cache_block table because that table is flushed enough so we don't have stale data on our pages.

<?php
/**
* Block callback.
*/
function test_block_view() {
 
$block = array();

 

// Get the URI without any query parameter.
 
$uri = parse_url(request_uri());
 
$cache_id = $uri['path'];

 

// Do we have something in cache ?
 
if ($cache = cache_get($cache_id, 'cache_block')) {
   
$block = $cache->data;
  }
 
// Otherwhise rebuild and cache it.
 
else {
   
$views_data = module_invoke('views', 'block', 'view', 'frontpage-block_1');
   
$block['subject'] = 'Frontpage';
   
$block['content'] = $views_data['content'];
   
cache_set($cache_id, $block, 'cache_block');
  }

  return

$block;
}
?>

You are here