1

I have a long if/else block within a for loop in my template and I wanted to cache all of it (it loops over a Matrix field, checking for different block types on each row and outputs the correct code as needed). However, in one of the ifelse blocks, I have a statement with a RAND parameter that I don't want cached. Something like this:

{% for block in entry.sidebar %}
    {% if block.type == "someType" %}
        ...Presentiaon code
    {% elseif block.type == "someType" %}
        ...Presentiaon code
    {% elseif block.type == "someType" %}
        {% set randomEntry = craft.entries.section("testimonials").order('RAND()').first() %}
    {% endif %}
{% endfor %}

My challenge is trying to find a way to cache this long block but still let the RAND work. My solution was to try to put the matrix field into a variable, cache that variable and then iterate over the variable's data (the thinking here that the variable has all the process-intensive DB queries). Something like this:

{% cache %}
    {% set myField = entry.myMatrixField %}
{% endcache %}

{% for block in myField %}
    {% if block.type == "someType" %}
        ...Presentiaon code
    {% elseif block.type == "someType" %}
        ...Presentiaon code
    {% elseif block.type == "someType" %}
        {% set randomEntry = craft.entries.section("testimonials").order('RAND()').first() %}
    {% endif %}
{% endfor %}

However, this fails after the template has been cached with an error that the 'myField' variable does not exist. So I'm thinking I can't do this?

Is there another way I could cache this? I considered breaking up the ifelse blocks into separate if/endif clauses and caching each except the one with the RAND paramater in it but I'm thinking that won't improve performance much if the for loop still has to run outside of it uncached.

1

Update: This doesn't work. Leaving it here temporarily in case it helps generate more ideas.

Haven't tried this myself, but you might try returning all testimonials and then use twigs random method to select one after the fact.

{% cache %}

    {% set myField = entry.myMatrixField %}

    {% for block in myField %}
        {% if block.type == "someType" %}
            {% set presentationCode %}
                ...Presentation code
            {% endset %}
        {% elseif block.type == "someType" %}
            {% set presentationCode %}
                ...Presentation code
            {% endset %}
        {% elseif block.type == "someType" %}
            {% set randomEntry = craft.entries.section("testimonials").find() %}
        {% endif %}
    {% endfor %}

{% endcache %}

{% if randomEntry %}
    {% set randomEntry = random(randomEntry) %}
    {% set presentationCode %}
        ...Presentiaon code
    {% endset %}
{% endif %}

{{ presentationCode }} 

Note: I suspect that you will need the .find() on the end of the ElementCriteriaModel statement so that it gets converted to an array.

Update: To do this you will also probably need to place all your presentation code in a variable and then display later in the template.

|improve this answer|||||
  • After rereading your problem, I'm realizing this may fail for the same reason that your solution failed; might not be able to cache variables. idk... let us know how it goes. – Douglas McDonald Jan 6 '15 at 4:33
  • Thanks Douglas. I think it might fail also - haven't tried it yet but will update with my findings. I wish there were a way to make exceptions within the cache tags like in EE's CE Cache. Maybe a feature request someday. – Mike Jan 6 '15 at 19:05
  • I did a simple test setting a variable and then retrieving it outside the cache tag. Doesn't work. So my answer will fail. Been trying to think of another work around but not coming up with anything. – Douglas McDonald Jan 6 '15 at 19:12
  • Craft cache blocks only store the html output within the blocks, so any variables that are defined within a cache block will not be available outside the cache block because they don't evaluate to html. You need to either define the variables outside of the cache blocks or test the html output of the cache block as suggested below. – Tortilaman Sep 3 '16 at 1:11
0

Here's another answer, although more of a hack than a solution. Test the output of the cached content and do something else if it's set to some predetermined value.

{% set content %}
    {% cache for 5 mins %}
        {% if block.type == "someType" %}
            ...Presentation code
        {% elseif block.type == "someOtherType" %}
            triggerTestimonials
        {% endif %}
    {% endcache %}
{% endset %}

{% if content|trim == "triggerTestimonials" %}
    {% set randomEntry = craft.entries.section("testimonials").order('RAND()').first() %}
    ...
{% else %}
    {{ content }}
{% endif %}
|improve this answer|||||
  • Thanks Douglas. No dice... the issue above is that if your first conditional (content|trim) is true, I essentially have to run the entire matrix loop again to put that random entry into the correct place in the output. So I guess you could say it's a solution for the latter case though. I've tried a couple other things with no luck so I might just end up using this to cover off some of the cases... I appreciate the input. – Mike Jan 7 '15 at 22:48

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.