I recently published a new Snippet for quickly caching the output of any MODX Element for a configurable amount of time. By default, it uses the Resource caching mechanism and stores it’s data uniquely by Resource, properties, and additional REQUEST parameters. So anytime the page is requested and the cache has expired, the Element will be processed fresh. And that’s just the simplest application…

A well-implemented caching strategy is critical to site efficiency

One of the biggest challenges in developing a dynamic website with a PHP-based CMS (or a CMS in any language for that matter) is making sure that it scales. Scalability is a topic of enormous scope however; there is more to consider than the quantity and frequency of traffic, or the amount of content being managed. You also have to consider your content, how often it really needs to be updated, and organizing your managed content properly. To combat this, I rarely call a Snippet in my MODX-managed sites uncached, and if I do, it has built-in caching that refreshes itself only when needed. So I thought, I wonder if I could just create a Snippet to cache other Snippets, or even Elements, with a generic, configurable caching system.

Well, it was easier than I imagined (I love it when that happens). I took the caching system I recently introduced to the getPage Snippet and quickly extracted it into a simple way to cache any Element. I call it getCache (I know, original, eh?). You can get the beta from your Revolution installation’s Package Management feature, online at MODX Extras, or help me maintain and document it at GitHub

You might consider using getCache to cache your fancy MostPopularPages snippet that counts user votes per page, for 15 minutes at least, so your server doesn’t choke to death. Or maybe you have a source of information that changes only on rare occasions, say a Snippet that makes a REST call to a web service, and you know there’s no reason to hit it more often than once every 6 hours. Whatever the scenario, getCache can help alleviate some of your precious processing power on every page request; all you need is a strategy for caching your content.

Here is a sample getResources call that is cached for 1200 seconds (20 minutes) via getCache. It may not seem like much to cache this one Snippet call for 20 minutes, but if you are getting 100 requests per second or more, you don’t want every request executing the query; it simply doesn’t make sense:

[[!getCache?
    &element=`getResources`
    &cacheExpires=`1200`
    
    &parents=`4`
    &where=`{"template:IN":[1,2,3]}`
    &sortbyTV=`eventDate`
    &sortdirTV=`ASC`
    &sortby=``
    &tpl=`getResourcesTpl`
]]

It is good to note that by default, getCache uses whatever you have configured as the system cache_handler. In Revolution by default, this is xPDOFileCache, which caches the data to file within the core/cache/ directory, but this can be overridden, either for the entire system, or for each cache partition, such as cache_resource or cache_scripts. In particular, if you have overridden the partial page cache by providing a cache_resource_handler setting, getCache will take notice and use this as well, since the caching of these calls is Resource specific in most cases. In this way, your custom caches will be cleared either when they expire, or when the cache for a Resource is deleted (including when the entire site cache is cleared manually). If you override, it would be your responsibility to make sure it was cleared along with the Resource or the entire site cache as appropriate for your needs.

Another simple example to prove it’s working; create a Snippet called time with the code below.

return strftime('%X');

Then put the following content in a cacheable Resource to see the cache update as configured:

<p>resource cached at: [[!getCache? &element=`time`]]</p>
<p>time last cached at: [[!getCache? &element=`time` &cacheExpires=`10`]]</p>
<p>current time is: [[!time]]</p>

Now just reload the page for a bit and you can see the caching at work. Note that since the default cacheExpires value is 0, the first call is cached when the Resource is and not cleared again until that Resource’s cache is cleared.

Anyway, if you value efficiency like I do, this is a great way to quickly apply a caching strategy and whatever point in the site life-cycle you happen to be in. Another win in my opinion for the flexibility that MODX Revolution brings to the Content Management table.

Look for future posts on more complex getCache configurations using memcache and some of the other more advanced properties of the Snippet and MODX Revolution’s highly customizable and granular caching system.