Is that possible to enable cache for everypage except a few exclusion? For instance, i don't want the a page to be cached because it is too dynamic.

Comments

moshe weitzman’s picture

the page cache only applies to anonymous users. so all registered users are already excluded.

unnamedstone’s picture

Thanks for your reply.

The page I want to exclude is dynamic even to anon users, that's why I want to figure out how to exclude a particular page.

luebbe’s picture

I've got the same problem. A status page that is created dynamically from database content. This page has to be excluded from caching for all users, otherwise the status doesn't make sense.

This sounds like I have to switch off the cache for the entire site or rewrite my status page into a drupal module.

Would it be possible to add a "don't cache" option to each node?

videojunky’s picture

Me third! I have a module that generates a random node out of my database but if I turn cache on, the module outputs the same node each time. I need something to exclude this module from being cached by drupals cache.
I use 4.5...

VideoJunky.Net

pfaocle’s picture

This would be handy for me, too. I have a single node containing PHP script which I attach to other nodes using the attached_node module. The output of this script is dynamic, and is based on which node you are viewing.

At the moment, I can view a node with the script node attached once, then all other nodes viewed afterwards show the same output, rather than generating it again.

This happens regardless of logged in/out status, and even when caching is disabled. I have also tried calling cache_clear_all() at the start of the script node.

---
paul byrne
web monkey - http://www.leafish.co.uk/

---
Paul Byrne
pfaocle.co.uk | CTI digital

luebbe’s picture

The "don't cache" option for the php filter format isn't honored if an anonymous user is accessing the page. A "TEMPORARY" cache entry is created, wich will be removed by a cache_clear_all call.

So I added a cache_clear_all call to cron.php. That removes all expired pages on each cron run.

Not perfect, but it works for me, because my dynamic pages are only updated every two hours.

videojunky’s picture

How exactly do I add the call to the cron.php?
and with drupal cache system how effective is it. I know when I have a good load of ppl my system load goes over 1 w/ a dedicated 2.4intel.
Right now I have cron running every 4 or 6 hours that way any news posted will be archived for searches the same day. If I use clear cache on the cron, my random post(content) button should change every cron run?
Or is there a command I can run with my random content module to clear cache for the current page?
Thanks

www.VideoJunky.Net

mariagwyn’s picture

I am having a similar problem to changes made to pages. While I have turned off the 'enable cache' I would like to turn it back on. However, changes made to page.tpl.php do not appear to anonymous users.

Can you give me the exact syntax of your fix so I can modify my cron.php? I tried just what you had above, but it is incomplete, and I am php ignorant (thought learning).

Thanks,
Maria

luebbe’s picture

Simply add the cache_clear_all(); line to your script

// $Id: cron.php,v 1.28 2005/01/09 09:22:38 dries Exp $

/**
 * @file
 * Handles incoming requests to fire off regularly-scheduled tasks (cron jobs).
 */

include_once 'includes/bootstrap.inc';
include_once 'includes/common.inc' ;

// If not in 'safe mode', increase the maximum execution time:
if (!ini_get('safe_mode')) {
  set_time_limit(240);
}

// Check if the last cron run completed
if (variable_get('cron_busy', false)) {
  watchdog('cron', t('Last cron run did not complete.'), WATCHDOG_WARNING);
}
else {
  variable_set('cron_busy', true);
}

// Iterate through the modules calling their cron handlers (if any):
module_invoke_all('cron');

// Clear all expired pages;
cache_clear_all();

// Clean up
variable_set('cron_busy', false);
watchdog('cron', t('Cron run completed'));

fonant’s picture

The caching is controlled by the result of variable_get('cache',0) when the user is anonymous and it's a GET request. This function in turn uses $GLOBALS['config']['cache'].

So to prevent a particular page being cached, while leaving the normal page cache on, simply set $GLOBALS['config']['cache'] to false somewhere in that page's code. The page will then not be cached at all, so no need for exit() functions to remove it from the cache later.

Thanks to Tolmács Márk for his comment in http://drupal.org/node/233979 that showed me the way.

My particular problem was for multi-page forms that were used by anon users. The entered values were stored in the session, so you could go backwards through the form pages. The problem was that the initial form page was always displayed with a GET request, so was being served from the page cache, rather than being generated with the correct default data. I now set the global variable above to false in my module's custom form_alter() function, when the form_id matches one of the affected forms.

http://www.fonant.com - Fonant Ltd - Quality websites

jguffey’s picture

Note to anyone else finding this,

It works, on my page-tpl.php file, but there is a minor typo in Fonat's code here.

Should be: $GLOBALS['conf']['cache'] not $GLOBALS['config']['cache'].

Thanks for the pointers Fonat!

bryan kennedy’s picture

Did anyone make any progress in how to exclude a specific node from the cache? I would like to do this for a page that updates every mintue so the cron process is not acceptable for me. I just need one page to ALWAYS pull new data from the database and the rest of the site to use the cache.

cidenton’s picture

I am using a global variable as a 'do not cache' flag. Just modify the function page_set_cache in bootstrap.inc (starting on line 262 in drupal 4.6.2) from:

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

  if (!$user->uid && $_SERVER['REQUEST_METHOD'] == 'GET') {
function page_set_cache() {
  global $user, $base_url, $do_not_cache;

  if (!$user->uid && !$do_not_cache && $_SERVER['REQUEST_METHOD'] == 'GET') {

Then in any node you want to exclude from the cache, set the global variable $do_not_cache to 1:

<?php $GLOBALS['do_not_cache'] = 1 ?>

and it will never be cached.

ymcp’s picture

Has there been any move to add this to the drupal core, (or perhaps to 4.7?)

It would be very useful to disable the drupal cache on a module-by-module basis.

For some modules (eg my current issue with captcha) it just doesn't seem appropriate to cache them since you would always want a "fresh" version to be generated.

Anybody?

MiniTheMan-1’s picture

I'm using 4.7.3 and experienced the same problem in combination with the guestbook.module. Does this 'hack' also work for this version? Where do i place the code in this version? The function page_set_cache doesn't exist in the bootstrap.inc.

Thanx in advance.

paolability’s picture

<?php $GLOBALS['do_not_cache'] = 1 ?>

How/where is this inserted into specific nodes?

fonant’s picture

Use the CacheExclude module? http://drupal.org/project/cacheexclude

Or manually set $GLOBALS['config']['cache'] to false at some point in the page's code, which is what the module does.

http://www.fonant.com - Fonant Ltd - Quality websites

luperry’s picture

I wrote a simple cache exclusion module, so that you don't have to hack the drupal core. it uses regular expression for page matching.


/**
 * Implementation of hook_help().
 */
function cache_exclusion_help($section) {
  switch ($section) {
    case 'admin/modules#description':
      return t('Exclude certain pages from being cached.');
  }
}

/**
 * Implemetaion of hook_settings
 */
function cache_exclusion_settings() {
  $form['cache_exclusion_list'] = array(
    '#type' => 'textarea',
    '#title' => t('Pages to exclude from caching'),
    '#default_value' => variable_get('cache_exclusion_list', ''),
    '#width' => 40,
    '#height' => 10,
  );
  return $form;
}

/**
 * Implementation of hook_exit().
 */
function cache_exclusion_exit($destination = NULL) {
  if ($destination == NULL) {
    $pages = explode("\n", variable_get('cache_exclusion_list', ''));
    $this_page = request_uri();
    foreach ($pages as $page) {
      if (ereg('^' . $page . '$', $this_page)) {
        global $base_root;
        cache_clear_all($base_root . $this_page);
        return;
      }
    }
  }
}

joepublicster’s picture

Thanks for this. It almost worked for me on 4.7.3 - the ereg call in cache_exclusion_exit wasn't matching the pages that I set in the settings since there was additional whitespace appended to each page. Once I trim'ed each page to strip the whitespace prior to the page check, everything was fine. Thanks for the code. Here's my version:

<?php
/**
 * Implementation of hook_help().
 */
function cache_exclusion_help($section) {
  switch ($section) {
    case 'admin/modules#description':
      return t('Exclude certain pages from being cached.');
  }
}

/**
 * Implemetaion of hook_settings
 */
function cache_exclusion_settings() {
  $form['cache_exclusion_list'] = array(
    '#type' => 'textarea',
    '#title' => t('Pages to exclude from caching'),
    '#default_value' => variable_get('cache_exclusion_list', ''),
    '#width' => 40,
    '#height' => 10,
  );
  return $form;
}

/**
 * Implementation of hook_exit().
 */
function cache_exclusion_exit($destination = NULL) {
  global $base_root;

  if ($destination == NULL) {
    $pages = explode("\n", variable_get('cache_exclusion_list', ''));
    $this_page = request_uri();
    foreach ($pages as $page) {
      $page = trim($page);
      if ( strstr($this_page, $page) !== false ) {
        cache_clear_all($base_root . $this_page);
        return;
      }
    }
  }
}
?>
kadarusj’s picture

The snippet below worked for me. And, I think it works better using the preg_match rather than ereg, just don't forget to trim and escape the slashes.

function cache_exclusion_exit($destination = NULL) {
global $base_root;

if ($destination == NULL) {
$pages = explode("\n", variable_get('cache_exclusion_list', ''));
$this_page = request_uri();
foreach ($pages as $page) {
$page = preg_replace("/\//", "\/",$page);
//echo $page." - ".$this_page."
";
if(preg_match("/".$page."/", $this_page)) {
db_query("DELETE FROM {cache} WHERE cid = '%s'", $base_root . request_uri());
}
}
}
}

Jason Kadarusman
Web Developer
Achieve Internet
1767 Grand Ave. Ste 2
San Diego, CA 92109

Crell’s picture

I hope you don't mind, but I've submitted that mini-module to CVS:

http://drupal.org/project/cacheexclude

If you have a CVS account, contact me and let me know if you want CVS access on it. You wrote it, I just packaged it up. :-) Cheers!

--
Larry Garfield
http://www.garfieldtech.com/blog

--
Larry Garfield
http://www.garfieldtech.com/
Thinking Functionally in PHP: https://leanpub.com/thinking-functionally-in-php

kadarusj’s picture

Is it possible for me to get a CVS account? Or how do I get a cvs account?

colan’s picture

Take a look at Maintaining projects with CVS for information on this.

isaac77’s picture

came across this post while trying to deal with a related issue. thought i'd post a link to my solution just in case it's helpful to anyone else who comes across this thread. thanks to those who posted here (a long time ago); these notes pointed me in the right direction.

i needed to force the page cache to clear frequently for just a few specific dynamic pages. (in my case, i wanted "upcoming events" queries to be re-run a few times per day, so that outdated events would be removed from the list. because new content was not being created frequently, the page cache was not being cleared often enough.)

i created a very simple module to delete specific pages each time cron.php is called. then i created a separate cron task that accessed those same pages, so that the page cache would be (almost) immediately re-populated with new data based on up-to-date calculations.

if this would help you, take a look at the code and more detailed explanation

ilfelice’s picture

I tried this in 4.7.5, and I get the following error after enabling the module:

warning: strstr() [function.strstr]: Empty delimiter. in /modules/cacheexclude/cacheexclude.module on line 41.

Anyone having the same problem?

Mumonkan’s picture

i also needed to exclude just a few pages from cache.... and found this page.

however, after a great deal of sleuthing i found that $GLOBAL['config']['cache'] wasnt working for me, but rather $GLOBALS['conf']['cache'] = FALSE is whats works.

??? i am not sure why this is. maybe its some kind of setting on our drupal setup or whatever, but just wanted to make a note of this here to save someone the sleuthing.

Alexandros78’s picture

Setting $GLOBALS['conf']['cache'] to FALSE can work for modules as well.

Just use the hook_init() to set it to false:
function mymodule_init() {
$GLOBALS['conf']['cache'] = FALSE;
}

This way the module will get executed every time, even for anonymous users!

lmeurs’s picture

Though an old thread, this might come in handy. Drupal 7 uses drupal_page_is_cacheable(FALSE) to prevent a page from caching, see https://api.drupal.org/api/drupal/includes%21bootstrap.inc/function/drup...

Laurens Meurs
wiedes.nl

angel.angelio’s picture

function mymodule_init(){
  if($_GET['q'] == 'path'){
        drupal_page_is_cacheable(FALSE);
  }
}

Don't forget to take in consideration the path alias. It does the trick with multi-step forms for anonymous users (when cache is activated).

awaller98’s picture

Cacheexclude was just what I needed...