1

Is it possible to clear the cache of individual node without regard to the minimum cache lifetime in the cache settings Drupal 7?

It seems like node_save clears the cache:

entity_get_controller('node')->resetCache(array($node->nid));

However, that respects the minimum cache lifetime.

This is an issue when unpublished saved nodes go from an unpublished to a published state. Users served from the cache can't see the page until it expires, and it's immediately shared on Facebook or Twitter, those who click get a page not found 404.

I'm stuck using the Clear all caches button on /admin/config/development/performance. That seems like a heavy-handed approach.

Is there a better way?

Is cache_clear_all(); (called with no-params) the programmatic equivalent of the Clear all caches button?

Thanks in advance for any help!

2
  • I think that an anonymous request to an unpublished page would result in a 403 (access denied) instead of a 404, assuming of course anon users don't have perms setup to see unpublished content. Is that what you are seeing? Either way I think the caching issue is the same, it would just be interesting if you were getting a 404 instead of a 403.
    – rjacobs
    Feb 12, 2015 at 18:58
  • @rjacobs I was going off of memory, thought it was 404, page not found, but it very well could be 403.
    – guinness74
    Feb 13, 2015 at 23:18

2 Answers 2

2

First, a couple contextual comments on all this:

  1. You are probably getting a 403 (Access Denied) message instead of a 404 (Not Found) message when visiting a previously unpublished page that was cached.
  2. The method call that you referenced (entity_get_controller('node')->resetCache(array($node->nid))) within node_save() does not have anything to do with the page cache, and is instead related to the static entity cache, which only has an impact on the current request. However, you are certainly correct that Drupal makes an effort to clear the page cache upon a node save, but that happens in node_form_sumbit() when it calls cache_clear_all() at the end.
  3. The cache clearing methods in Drupal are very strange and non-intuitive. I've seen entire threads erupt in passionate arguments and misunderstandings over the workings of cache_clear_all() and DrupalDatabaseCache::clear().

If cache_clear_all() is called without any arguments, as is the case on a node update, only the page and block cache bins will be targeted for clearing. That's fine as it's presumably the page cache that matters in your case, but as you noted the "Minimal Cache Lifetime" will be respected. The exact logic used to respect this "Minimal Cache Lifetime" (in DrupalDatabaseCache::clear()) might make your mind melt... but that's an aside.

As indirectly noted in another answer, you can call cache_clear_all() with a specific node URL to force the needed page_cache entry to be cleared. This will do the job independent of the "Minimal Cache Lifetime" which, IMHO, is quite non-intuitive. Thankfully there are tools that account for all this non-intuitive logic for us, like the Expire module. Not only does it have the ability to target certain actions in Drupal (such as a node update), and clear the cache when they happen, but it will do it in such a way that the "Minimal Cache Lifetime" is factored-in and bypassed as needed. There is an old issue thread here that seems to talk about this a little more.

Also, if you have another page cache active (Varnish, Boost, etc.) they may be suspect too, and may be returning a previously cached version of the request independent of the local Drupal page cache. If you have an external cache like this in place you should check its own settings along with the the core "Expiration of cached pages" setting (just below the "Minimal Cache Lifetime" setting). Once again, the Expire module can help here as it also integrates with external caches to sync their expirations with Drupal updates.

4
  • Thank you for your thoughtful reply. Like I replied to @DEVARAJJOHNSON below this solution did not work. I implemented his cache_clear_all() solution, and set my Minimum cache lifetime to 30 minutes. After I made an edit to my node, the original version was still being served to an anonymous user. Any idea why that would be the case? I tested on my development environment so there is no other caching running. "Expiration of cached pages" is set to none in both development and production environments.
    – guinness74
    Feb 16, 2015 at 16:10
  • Humm, interesting. If you want to trigger the cache clear manually in your own code then it's best to confirm 100% that your hook_node_update() implementation is actually firing correctly. It's also possible that the $nodeurl value you are using in your calculation (via the url() call) is not matched to the correct cache id (cid) that needs to be cleared in cache_clear_all() for anon users. Pages in the cache are keyed by the full URL, so if you edit the page via a domain that's different from what anon users access it with, the clearing may not be working.
    – rjacobs
    Feb 16, 2015 at 18:05
  • If your domains are matched while editing and for anon users, you may be able to get the needed cid/nodeurl with $nodeurl = url('node/'. $node->nid, array('absolute' => TRUE) to force a full URL. My guess is also that the Expire module compensates for all this already, so trying it may be a good part of your testing process as well.
    – rjacobs
    Feb 16, 2015 at 18:11
  • $nodeurl = url('node/' . $node->nid, array('absolute' => TRUE)); seemed to do the trick, thank you!
    – guinness74
    Feb 22, 2015 at 2:32
0

This is the simple way to clear cache For example:

function YOUR_MYMODULE_node_insert($node) {
  drupal_flush_all_caches();
}

or to clear only the static page cache after a node has been updated:

function YOUR_MYMODULE_node_update($node) {
  $nodeurl = url('node/'. $node->nid);
  cache_clear_all($nodeurl, 'cache_page');
}

refer this for more info

How to delete cache after updating/deleting/adding new content using hooks?

4
  • Thank you! Will cache_clear_all($nodeurl, 'cache_page'); ignore the minimum cache lifetime and delete the cached entry like the Clear all caches button? In other words, will the node show up on the front-page and be available to visitors?
    – guinness74
    Feb 12, 2015 at 18:21
  • drupal_flush_all_cache() will do it for you and cache_clear_all($nodeurl,'cache_page') will clear cache for that particular node. Feb 12, 2015 at 18:24
  • 2
    you might want to look into using the expire module as well. drupal.org/project/expire
    – mikeytown2
    Feb 12, 2015 at 19:12
  • @DEVARAJJOHNSON - This solution did not work. I added the code you suggested, the cache_clear_all solution, and set my Minimum cache lifetime to 30 minutes. After I made an edit to my node, the original version was still being served to an anonymous user.
    – guinness74
    Feb 14, 2015 at 17:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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