tags:

views:

21

answers:

1

Hi there,

This should be a very simple question, but I'm finding it surprisingly hard to find an answer.

I'm creating custom pages using hook_menu that have both static content and dynamic aspects, (mainly from sql queries and views embeds etc...). My question is, how does drupal's cache system treat these custom pages?

I'm concerned because as the traffic ramps up on some occasions, I feel like I need some kind of caching control over the display of these pages, but at this point, I have no idea if they're automatically being cached, or if I need to somehow specify to drupal that I do indeed want them cached.

Just to clarify, these pages are not admin pages, but are accessible by anyone.

A: 

The result of a menu callback is cached only when the menu callback returns the output; when the menu callback prints the output, it's not cached.

The code execute to bootstrap Drupal when a page is requested is the following:

require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

$return = menu_execute_active_handler();

// Menu status constants are integers; page content is a string.
if (is_int($return)) {
  switch ($return) {
    case MENU_NOT_FOUND:
      drupal_not_found();
      break;
    case MENU_ACCESS_DENIED:
      drupal_access_denied();
      break;
    case MENU_SITE_OFFLINE:
      drupal_site_offline();
      break;
  }
}
elseif (isset($return)) {
  // Print any value (including an empty string) except NULL or undefined:
  print theme('page', $return);
}

drupal_page_footer();

drupal_page_footer() is the function that caches the result.

function drupal_page_footer() {
  if (variable_get('cache', CACHE_DISABLED) != CACHE_DISABLED) {
    page_set_cache();
  }

  module_invoke_all('exit');
}

page_set_cache() is the function that does the real work.

function page_set_cache() {
  global $user, $base_root;

  if (!$user->uid && $_SERVER['REQUEST_METHOD'] == 'GET' && page_get_cache(TRUE)) {
    // This will fail in some cases, see page_get_cache() for the explanation.
    if ($data = ob_get_contents()) {
      if (variable_get('page_compression', TRUE) && extension_loaded('zlib')) {
        $data = gzencode($data, 9, FORCE_GZIP);
      }
      ob_end_flush();
      cache_set($base_root . request_uri(), $data, 'cache_page', CACHE_TEMPORARY, drupal_get_headers());
    }
  }
}

The content is compressed (if the zlib is enabled), and saved in the cache.

If you want the cache the output of a custom menu callback, then you just need to return the output, instead of printing it directly.

function mymodule_callback() {
  // …
  return $output;
}

Instead of caching the output of the page, you can cache the data the module used to build its output. If, in example, the output data is obtained with an SQL query, you can cache the result of the query.

kiamlaluno
Thanks for all that info kiamlaluno. I am returning the output instead of printing it directly, so if I understand you correctly, that means my page output is being cached - once I turn on caching of course. Right?
Michael D
The page cache is only used for anonymous users (that is why `page_set_cache()` checks `$user->uid`), for pages that use GET requests, and if there are no messages set with `drupal_set_message()`. If the page contains a form created with form API, then it will be used another cache.
kiamlaluno
Believe it or not kiamlaluno, even with all the words you've used to explain this to me, and thanks for those BTW...I still am not entirely sure if the answer to the question I asked is "yes". It looks more and more to me like the answer must be yes, but I sure wish you could just come right out and say yes or no. Thanks again.
Michael D
It's cached, but just for anonymous users.
kiamlaluno