2

I'm looking for a way to disable the template cache ({% cache %} tags) for the entire request based on a specific condition (not just based on the current environment). In this case, the condition is a query parameter (something like ?nocache=1), but I'm also looking for a general solution to this. There is, of course, the enableTemplateCaching general config setting, which I could use to toggle the template cache on and off:

// config/general.php

$someCondition = true;

return [
    '*' => [
         'enableTemplateCaching' = $someCondition,
    ],
];

The problem is that the config is included super early during the request lifecycle, before the Craft::$app object is even constructed. So I can't use Craft::$app->request->getQueryParam('nocache') or anything else from the API. For query parameters specifically, I could access $_SERVER['REQUEST_URI'] directly, but that feels kind of dirty. And it doesn't solve the problem if I need access to anything from the API to determine whether to enable caching or not.

I've checked if there's a hook in the TemplateCaches service I could use, but it doesn't look like it. The other solution would be to include the condition in every {% cache %} tag manually, but that's error-prone and noisy.

Is there a more general solution to turning off {% cache %} tags based on a specific condition for the current request?

1 Answer 1

2

I can't think of a different way to conditionally enable template caching (globally, i.e. not per {% cache %} tag) other than to conditionally set the enableTemplateCaching config setting to either true or false.

To your specific use case, I wouldn't worry about simply accessing the $_GET superglobal to look for that nocache param. This is essentially all that Craft itself does under the hood, when you use Craft::$app->getRequest()->getQueryParams() – except that Craft will also UTF8-encode and memoize the params, which shouldn't be critical.

So something like this should work fine:

use craft\helpers\App;

$disableTemplateCaching = App::parseBooleanEnv($_GET['nocache']);

return [
    '*' => [
         'enableTemplateCaching' = !$disableTemplateCaching,
    ],
];

Another option is to set the config setting a bit later in the request lifecycle. For that, you can't use config/general.php, but will need to create a custom module, adding the relevant logic within an appropriate event listener (setting/overriding the config setting can be done by accessing the Config service).

Using the craft\web\Application::EVENT_INIT event seems to work nicely; the below would go into your module's init() method:

use Craft;
use craft\helpers\App;
use craft\web\Application;
use yii\base\Event;

Event::on(
    Application::class,
    Application::EVENT_INIT,
    static function (Event $event) {
    
        // Get the "nocache" query param value
        $noCacheParamValue = Craft::$app->getRequest()->getQueryParam('nocache');
    
        // Make sure it's a boolean
        $disableTemplateCaching = App::parseBooleanEnv($noCacheParamValue);
    
        // Set the enableTemplateCaching config setting using the Config service
        Craft::$app->getConfig()->getGeneral()->enableTemplateCaching = !$disableTemplateCaching;
    
    }
);
1
  • 1
    Thanks for the thoughtful response! You're right, the first approach should be alright, and using $_GET is indeed a bit simpler than $_SERVER. Though the second approach is even better, changing the config value on init is a great idea! Might lead to some head-scratching for other developers though, so for this approach I'll want to stick a comment in general.php explaining that the value might be changed by the module.
    – MoritzLost
    Mar 14 at 9:50

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.