1

So background: I'm making a caching plugin that clears our site and CDN caches when content is saved in the administrator backend. In this instance, I want to clear the site cache for one group.

My original attempt looked something like this:

$cache = JFactory::getCache('cachegroup');
$cache->clean();

That didn't work. I did some research and saw SharkyKZ in the Joomla forums recommend this structure:

$cache = JCache::getInstance('callback');
$cache->clean('cachegroup');

That also didn't work for me. I suspected it had something to do with the fact that caching is disabled on our site, so I tried adding $cache->setCaching(1); to both sets of code and that didn't work either.

Finally I dug into the Joomla code and looked at how their cache component handles it; and ended up with this working code:

$conf = JFactory::getConfig();

$options = array(
    'defaultgroup' => '',
    'storage'      => $conf->get('cache_handler', ''),
    'caching'      => true,
    'cachebase'    => $conf->get('cache_path', JPATH_SITE . '/cache')
);

$cache = JCache::getInstance('', $options);
$cache->clean('cachegroup');

So I have working code, but I would...

  1. Like to understand why it works, and
  2. Like to know if there is a simpler or superior way to accomplish this.

Update

This problem doesn't seem to be reproducible within a site template, but I still have the problem within a plugin. So I'm going to give an expanded example of the code structure to help spot problems.

<?php

// No direct access.
defined('_JEXEC') or die;

class plgContentFncaching extends JPlugin
{
    function onContentAfterSave($context, $article, $isNew) {
        // Banner items
        if($context == "com_banners.banner") {
            // Does not work
            plgContentFNCaching::problemClearBannerCache();

            // Works
            plgContentFNCaching::workingClearBannerCache();
        }
    }

    function problemClearBannerCache() {
        $cache = JFactory::getCache('pinnedbanners');
        $cache->setCaching(1);
        $cache->clean();
    }

    function workingClearBannerCache() {
        $conf = JFactory::getConfig();
        
        $options = array(
            'defaultgroup' => '',
            'storage'      => $conf->get('cache_handler', ''),
            'caching'      => true,
            'cachebase'    => $conf->get('cache_path', JPATH_SITE . '/cache')
        );

        $cache = JCache::getInstance('', $options);
        $cache->clean('pinnedbanners');
    }
}
16
  • I do not really understand what you would like to clean from the cache when the caching is disabled basically? Your last code sample In your question however shows that the caching is set to true. Your question is ambiguous this way.
    – Zollie
    May 22 '20 at 9:55
  • So it looks like that your last code sample works because in the options caching gets enabled. Thus clean() method returns true.
    – Zollie
    May 22 '20 at 9:59
  • I also do not see however why the other codes do not work at setCaching(1).
    – Zollie
    May 22 '20 at 10:38
  • The reason is that I want to prevent Joomla and third party apps from caching. Then when I want to cache something, I just set caching to 1 for the group. This has worked pretty well until I wanted to clear the cache!
    – Obscerno
    May 22 '20 at 11:30
  • 1
    :) we cleared that from every angle.
    – Zollie
    May 24 '20 at 11:16
1

After some testing - and as @Obscerno stated - in some plugins the default cache directory is going to be on administrator path. It became obvious that depending on the triggered plugin events, the cache object is using different cachebase directory. If the plugin event is triggered from the back-end then the default cache directory is going to be on .../administrator/cache path on default administrator root, and if the plugin event is triggered from front-end then the normal default cache directory will be used. So, it depends on which plugin event you are running your cache handling methods.

Thus you can and you should define 'cachebase' after you called the Cache object:

    $myCache = JFactory::getCache('my_cache_plugin');
    $myCache->options['cachebase'] = JPATH_SITE . '/cache';
    $myCache->setCaching(1);

    // var_dump($myCache); die; // debug/check

    $dataToCache = "<h2>From the content plugin on aftersave event this works now</h2>";

    $myCache->store($data = $dataToCache, $id = 'yep1', $group = 'my_cache_plugin'); // you will find the cached data in the 'cache/my_cache_plugin' subfolder

    $myCache->clean('my_cache_plugin', 'group'); // $myCache->clean(); also deletes this cache folder.
0
1

The problem has nothing to do with the cache being disabled. It is that the plugin is using a different cachebase setting than the cache that saved the data.

The cache that saved the data used the site cache folder located at /cache, while the plugin is using the cache folder located at /administrator/cache. It doesn't see the data because it's looking in the wrong place.

The reason the working code given in the question works is because it explicitly sets the cachebase to the site cache:

$options = array(
    'defaultgroup' => '',
    'storage'      => $conf->get('cache_handler', ''),
    'caching'      => true,
    'cachebase'    => $conf->get('cache_path', JPATH_SITE . '/cache') // <- Here.
);

As far as compacting the code goes, you can get away with this:

$options = array('caching' => true, 'cachebase' => JPATH_SITE . '/cache');
$cache = JCache::getInstance('',$options);
$cache->clean('cachegroup');
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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