7

I'm trying to set a cache duration as an environment variable.

I set up various environment variables and know they are being referenced correctly in my templates because I can print out the values of the variables in my templates.

return array(

    '*' => array(
        'environmentVariables' => array(
            'cacheDuration'          => '1 week',
            'cacheDurationQuantity'  => 1,
            'cacheDurationUnit'      => 'week',
        ),
    ),
);

I initially started with this cache tag...

{% cache for craft.config.environmentVariables.cacheDuration unless craft.config.devMode %}...{% endcache %}

...but I got this error:

Unexpected token "name" of value "craft" ("number" expected)

This had me thinking that perhaps Craft or Twig is expecting an integer immediately after the "for" keyword. Thus, I broke my cacheDuration variable into two parts: quantity which is an integer and unit which is a string.

{% cache for craft.config.environmentVariables.cacheDurationQuantity craft.config.environmentVariables.cacheDurationUnit unless craft.config.devMode %}...{% endcache %}

I still got same error as above. This inspired me to try:

{% set duration = 1 %}
{% cache for duration craft.config.environmentVariables.cacheDurationUnit unless craft.config.devMode %}...{% endcache %}

This time, I got a slightly different error.

Unexpected token "name" of value "duration" ("number" expected)

This has me thinking that any variable evaluated as expected in the duration parameter of the cache tag. However, other variables (like craft.config.devMode) are interpreted fine for other parameters of the cache tag.

Can anyone else confirm this or share insight into this?

  • Can you please tell me why you want to use cache duration? I am curious because I did not see a use case for it yet. – carlcs Jun 18 '14 at 18:32
  • I have cache tags in several places throughout my site. The cache duration might need to change from time to time depending on how often the site will be updated, which will vary during different parts of the year. The idea is to abstract the duration into one spot to where I can change the duration for all tags easily. – Wes Rice Jun 18 '14 at 20:21
  • 1
    Aren't cached template parts updated as soon as you make changes to your entries in the backend? That's why I don't understand the need to set a duration. – carlcs Jun 18 '14 at 21:13
  • 1
    True, but I actually have some parts of templates that are being pulled from other data sources, like twitter. Setting cache durations via a variable for those situations would be convenient. – Wes Rice Jun 18 '14 at 21:24
6

The error you're encountering is part of how Pixel & Tonic wrote the cache tag. In short, variables will not work for what you're trying to accomplish. For the longer explanation...

Tags in Twig are made up of tokens. So strings, numbers, variables, functions, tags, and filters are all tokens. When Twig is parsing a tag, it reads all the tokens and checks it against rules in a Twig extension.

The cache tag after seeing a 'for' token will only accept a number as the next token. Not a variable, or a string, or anything else. The bit typed into the template must be a number. For the duration unit, it checks what's there against a list they have already defined. Again, a variable won't work here. Likewise, the 'until' token looks for a date that can be parsed by PHP's strtotime, and 'unless' looks for something that gives it true or false.

You can accomplish the very same thing using built-in config settings. The cacheDuration setting will do as it says using the PHP Interval Specification. If you have a specific cache storage you'd like to use you can use cacheMethod. Setting these will let you use the cache tag without any extra configuration on the tag itself.

| improve this answer | |
4

Wes, there is a built in config setting for cacheDuration. See docs for General config settings:

"cacheDuration": Also used by the {% cache %} template tag if no expiration time is specified as a parameter.

Example config:

return array(
    '*' => array(
        'cacheDuration' => '4 years',
        'environmentVariables' => array(),
    ),
);
| improve this answer | |
  • I originally accepted this, but I want to make sure that this is correct. Is there a difference between data caching and file caching duration? The docs say this parameter is the default for data caching. – Wes Rice Jun 18 '14 at 20:18
  • There is also the possibility that I'm misunderstanding caching in general here and that all caching is "data" caching. However, my understanding is that template caching compiles the twig templates and caches them, which in my mind is file based caching, which is different than data caching. – Wes Rice Jun 18 '14 at 20:25
  • Ouuups, I did't see that this is for data caching. My answer is definitely wrong then. Can I delete the answer or what can I do now? – carlcs Jun 18 '14 at 21:11
  • If Bryan is right, there is probably no difference in these cache settings. Undeleted this again. – carlcs Jun 19 '14 at 13:14
  • I double checked the template caching in the source, and made sure it used the config settings. So yeah, we're both correct. – Bryan Redeagle Jun 19 '14 at 13:16
2

You could use the cache tags until parameter and calculate the next expiration date from your "cacheDuration" config variable.

return array(
    '*' => array(
        'cacheDuration' => 604800, // 1 week
    ),
);

Use Twig's round filter to round up from "now" to the next week.

{% set duration = craft.config.cacheDuration %}
{% set next = (now|date('U') / duration)|round(0, 'ceil') * duration %}

{% cache until next|date('c') %}
{% endcache %}
| improve this answer | |

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.