<p><strong>Update:</strong> This doesn't work. Leaving it here temporarily in case it helps generate more ideas.</p>

<p>Haven't tried this myself, but you might try returning all testimonials and then use twigs <a href="http://twig.sensiolabs.org/doc/functions/random.html" rel="nofollow">random</a> method to select one after the fact.</p>

<pre><code>{% 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 }} 
</code></pre>

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

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

CC BY-SA 3.0
2016-09-03T01:11:49.550Z
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
CC BY-SA 3.0
2015-01-06T04:33:40.903Z
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
CC BY-SA 3.0
2015-01-06T19:05:20.380Z
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
CC BY-SA 3.0
2015-01-06T19:12:11.083Z
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
CC BY-SA 3.0
2015-01-06T00:45:29.753Z
2015-01-06T19:14:02.863Z
2015-01-06T19:14:02.863Z
Douglas McDonald
<p>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.</p>

<pre><code>{% 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 %}
</code></pre>

CC BY-SA 3.0
2015-01-07T22:48:06.247Z
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
CC BY-SA 3.0
2015-01-06T19:53:08.160Z
2015-01-06T19:53:08.160Z
Douglas McDonald
<p>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:</p>

<pre><code>{% 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 %}
</code></pre>

<p>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:</p>

<pre><code>{% 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 %}
</code></pre>

<p>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?</p>

<p>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.</p>

<cache><variable><performance>
Caching variables for use elsewhere in a template?
# Caching variables for use elsewhere in a template?

(Asked by: username_0 on 2015-01-06)

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.

**Tags:** cache, variable, performance

---

## 2 answers

### Answer by username_1 on 2015-01-06. Score: 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.

> **Comments:**
> **username_1**: 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.  
> **username_0**: 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.  
> **username_1**: 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.  
> **username_2**: 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.  

---

### Answer by username_1 on 2015-01-06. Score: 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 %}

> **Comments:**
> **username_0**: 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.  

---

