Clearing the Cache for Selected Resources

Learn how to clear the cache for multiple Resources automatically when saving another one—and why you might want to do so.

By Bob Ray
April 25, 2022
Clearing the Cache for Selected Resources

You probably know that if you’re using the CacheMaster Extra, it will clear the cache for the Resource you are currently working on when you save it. But what if you need to clear the cache for one or more other Resources as well. For example, you might want to clear the cache for the Home Page whenever a Resource is saved so that a cached getResources tag on the Home Page will get current information.

The answer is a Plugin attached to the OnDocFormSave System Event.

The Code

/* Comma-separated list of the resources you want to clear */
$docs = '1,12,23';
$docIds = explode(',',  $docs);

foreach($docIds as $docId) {
    $doc = $modx->getObject('modResource', $docId);
    $ctx = $doc->get('context_key');
    $ck = $doc->getCacheKey();
    /* We need to replace the mgr context here */
    $mgrCtx = $modx->context->get('key');
    $cKey = str_replace($mgrCtx, $ctx, $ck);

    $modx->cacheManager->delete($cKey, array(
       xPDO::OPT_CACHE_KEY => $modx->getOption('cache_resource_key', null, 'resource'),
       xPDO::OPT_CACHE_HANDLER => $modx->getOption('cache_resource_handler', null,
       xPDO::OPT_CACHE_FORMAT => (integer)$modx->getOption('cache_resource_format', null,
           $modx->getOption(xPDO::OPT_CACHE_FORMAT, null, xPDOCacheManager::CACHE_PHP))

How It Works

The Plugin code just loops through the Resources and clears the cache for each one. If you only want to clear the Home Page, you could use this for the first line:

$docs = $modx->getOption('site_start');

Using the site_start System Setting here means that the code will keep on working even if you switch to a different Home Page.

The code that directs the cacheManager to clear the cache for a specific Resource is a little difficult to follow. That’s because it could be used in conjunction with a variety of third-party cache handlers. In the default MODX setup, it gets the documents cache key with $doc->getCacheKey(), then tells cacheManager to delete the item with that key, sending along some parameters to control the action. In the default configuration, these just tell CacheManager the name, location, and format of the cache file and what to do with it (delete it).

This code needs a little explanation:

$ctx = $doc->get('context_key');
$ck = $doc->getCacheKey();
/* We need to replace the mgr context here */
$mgrCtx = $modx->context->get('key');
$cKey = str_replace($mgrCtx, $ctx, $ck);

In the first line, we get the context that the Resource is in by grabbing its context_key field. Then, we ask the Resource for its cache key. Most of the time, the cache key is just a partial path to the cache file. So far, so good, but there is a quirk in the getCacheKey() method. It’s meant to be called in the front end, where the current context will be the context of the Resource and the context key (e.g., 'web') will be part of the path to the Resource’s cache file.

When called in the MODX Manager, though, getCacheKey() uses the name of the current context instead (usually mgr). That makes the path to the cache file wrong until we substitute the Resource’s actual context_key for the name of the Manager context in the string.

The Manager context doesn’t have to be called 'mgr', so to be on the safe side, we get it with $modx->context->get('key'). Then, we use str_replace() on the cache key to replace the key of the Manager Context with the context_key we got from the Resource. Most of the time, this code will just be replacing mgr with web.

Bob Ray is the author of the MODX: The Official Guide and dozens of MODX Extras including QuickEmail, NewsPublisher, SiteCheck, GoRevo, Personalize, EZfaq, MyComponent and many more. His website is Bob’s Guides. It not only includes a plethora of MODX tutorials but there are some really great bread recipes there, as well.