1

I run a flash card game embedded as a block in a Drupal 7 site.

Below that main block I display 3 further blocks for the winners of the previous and current week and top 7 best players:

enter image description here

And these 3 blocks are really dragging the performance of my web site (loading page is taking 5-10 seconds more than without them). I'd prefer them to be cached every 15-30 minutes because the weekly top 7 doesn't change often.

How could I do that - without jeopardizing my main block with the game? I.e. the main block contains flash vars specific to each user (his authentication hash) - this one block may not cached and served to any other user.

Below is my code:

pref.info -

name = Pref
description = Pref module
package = Pref
core = 7.x
files[] = pref.module

pref.module -

function pref_block_info() {
  return array(
    'pref_main' => array(
      'info' => t('Display flash game for auth. users'),
      'cache' => DRUPAL_NO_CACHE,
    ),
    'pref_winner' => array(
      'info' => t('Show the winner of the last week.'),
      'cache' => DRUPAL_NO_CACHE,
    ),
    'pref_leader' => array(
      'info' => t('Show the leader of the current week.'),
      'cache' => DRUPAL_NO_CACHE,
    ),
    'pref_top' => array(
      'info' => t('Show the top 10 of the current week.'),
      'cache' => DRUPAL_NO_CACHE,
    ),
  );
}

function pref_block_view($block_name = '') {
  global $user;
  $viewer_id = $user->uid;

  if ($block_name == 'pref_main') {
      .... # may not be cached
      return array(
        'subject' => '',
        'content' => '...here I return the .swf file + user-specific hash...');
  } else if ($block_name == 'pref_winner') {
      .... # should be cached
  } else if ($block_name == 'pref_leader') {
      .... # should be cached
  } else if ($block_name == 'pref_top') {
      .... # should be cached
    $result = db_query("
select u.id,
        u.first_name,
        u.female,
        u.city,
        m.money,
        u.login > u.logout as online
from pref_users u, pref_money m where
        m.yw=to_char(current_timestamp, 'IYYY-IW') and
        u.id=m.id
order by m.money desc
limit 7
");
    $i = 0;
    $list = array();
    foreach ($result as $record) {
      $list[] = user_link($record) . ($i++ > 0 ? '' : ' »');
    }
    $theme_args = array('items' => $list, 'type' => 'ol');
    $content = theme('item_list', $theme_args);
    return array(
      'subject' => 'Семерка лучших',
      'content' => $content,
    );
  }
}

For module caching I probably should enable it in the /admin/config/development/performance and then use some other constant instead of the DRUPAL_NO_CACHE (but which one to take from the includes/common.inc)?

  • I think that this may be specific to 7 but not 7.2. Can you change the title to reflect this? – Jeremy French Jun 29 '11 at 13:03
  • How do I know that? And I'm interested in the answer for the version I'm running. – Alexander Farber Jun 29 '11 at 13:30
  • 1
    There are very few changes between 7.0 and 7.2, it benefits the site in general if you try to be as version un specific as possible. After all in a few months you may be running 7.4. It may also help you get an answer as people you know 7.x may not look at a 7.2 specific question. – Jeremy French Jun 29 '11 at 13:34
2

A simple solution would be to cache the output instead of caching the block. This would be done in your hook_block_view implementation.

It could look like this:

...
$cache = cache_get('pref_pref_leader', 'cache_block');
// Return cache if possible.
if (!empty($cache) && isset($cache->data) && !empty($cache->data)) {
  return $cache->data;
}

// no cache, generate the output.
...
$content = ...;
$block = array(
  'subject' => 'Семерка лучших',
  'content' => $content,
);
// Cache for 30 mins.
cache_set('pref_pref_leader', $block 'cache_block', time() + 1800);
return $block;
...

See documentation for

  • Do you mean !empty($cache->data) above? And how do I check that the cache isn't older than 30 minutes - or is it automatically deleted otherwise? – Alexander Farber Jun 29 '11 at 13:00
  • And do I have to use 'cache_block_1', 'cache_block_2', ''cache_block_3' or just 'cache_block' for all 3 different modules? – Alexander Farber Jun 29 '11 at 13:01
  • 1
    @Alexander: Yeah there were a ! missing. You can cache all the blocks in at once if you like, or cache them one by one. I would prefer the letter. When you use cache_set, you set a cache expire time, thus the $cache will be empty once the cache expires and would have to be cached again with new info. cache_block is the caching table where you store the cache, you so need to use cache_block for them all, the first name is the name for the cache which should change for each block. – googletorp Jun 29 '11 at 14:09
  • 1
    The cache_set() call sets how long the cache entry is valid. The second argument is the name of the so called "cache bin", which is the database table in which the cache is stored with the default cache backend. You can only use one of the defined values. So, only 'cache_block'. The first arguments need to be unique however. – Berdir Jun 29 '11 at 14:13
  • I've also noticed, that as admin user nothing seems to be cached – Alexander Farber Jun 29 '11 at 20:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.