Skip to content

Instantly share code, notes, and snippets.

@jeromecoupe
Last active August 29, 2015 14:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jeromecoupe/cbac5f271fea0939fa88 to your computer and use it in GitHub Desktop.
Save jeromecoupe/cbac5f271fea0939fa88 to your computer and use it in GitHub Desktop.
Trouble figuring out stash caching / parse order
{!--
I have a complex template, fully cached.
The only thing I don't want to cache is a list of random testimonials
that has to change every time the page is loaded.
***
Some things I would like to understand, pretty please
1. when just using the {stash:nocache} tags, the list is set AFTER the getters are processed, which sound normal given the oignon thing
2. To correct that, I used process=end on the get_list
3. That works as expected but my conditionals are not parsed. Had to add parse_conditionals="yes" for it to work ... which I never knew I could do (didn't find it in the doc)
Am I overcomplicating this ? Is there an easier way to do it ?
--}
{!-- stash caching --}
{exp:stash:cache bundle="mybundle"}
{!-- layout used --}
{stash:embed:layouts:page}
{!-- set testimonials and don't cache (randomized: need to change on each page load) --}
{stash:nocache}
{exp:stash:set_list name="testimonials" parse_tags="yes"}
{exp:channel:entries disable="categories|category_fields|member_data|pagination|trackbacks" channel="testimonials" status="open" orderby="random" dynamic="no" limit="3"}
{stash:st_text}{cf_testimonial_text}{/stash:st_text}
{stash:st_author}{cf_testimonial_author}{/stash:st_author}
{stash:st_function}{cf_testimonial_function}{/stash:st_function}
{/exp:channel:entries}
{/exp:stash:set_list}
{/stash:nocache}
{!-- Build page content --}
{exp:stash:set name="content"}
{stash:nocache}
{!-- Get random testimonials--}
{exp:stash:get_list name="testimonials" prefix="stashprefix" process="end" parse_conditionals="yes"}
{if stashprefix:count == 1}<ul>{/if}
<div class="testimonial">
<blockquote class="testimonial__quote"><p>{stashprefix:st_text}</p></blockquote>
<p class="testimonial__author">{stashprefix:st_author}</p>
<p class="testimonial__function">{stashprefix:st_function}</p>
</div>
{if stashprefix:count == stashprefix:total_results}</ul>{/if}
{if stashprefix:no_results}<p>No Testimonials Found</p>{/if}
{/exp:stash:get_list}
{/stash:nocache}
{/exp:stash:set}
{/exp:stash:cache}
@croxton
Copy link

croxton commented Aug 12, 2014

The key to understanding all this is that you are saving a single flattened and partially rendered cache of your template code with the {exp:stash:cache} tag pair. If you open up Mustash and take a look at the variable generated by code above it will make more sense.

When your page is first viewed, your 'getter' code ({exp:stash:get_list name="testimonials"}) is injected into a specific position within the layout template ({stash:embed:layouts:page}) via the 'content' variable. The layout template is in turn replaced into the root template above the 'setter' code ({exp:stash:set_list name="testimonials"}), because that's where you've placed the embed.

The getter and setter code remain unparsed as you have escaped them by surrounding with {stash:nocache}.

Thus the final cache saved by {exp:stash:cache} is the markup of your html page with only the escaped setter and getters remaining as un-parsed EE tags.

When you next visit the page Stash retrieves the cache rather than regenerating the page, and tries to parse any un-parsed tags it finds. Parse order still applies - if your setter occurs after the getter in the parse order of the cached/compiled template, then you need to use process="end" on the getter to force it to be parsed later than the setter. And, as you have then moved your getter to the end of parsing, you need to do any parsing that might be required yourself. Hence you need parse_conditionals="yes" to parse conditionals when using process="end".

Does that make sense?

Note that you have indeed complicated things by separating the setter and getter. Since they are dependent on one another it would be reasonable and more legible to put them within the same {stash:nocache} region inside the content variable, and in the right order (setter first, followed by getter). Then you can eliminate the process="end" and parse_conditionals="yes"

@jeromecoupe
Copy link
Author

It does make sense. Thanks for the thorough explanation ... I just like to get to the bottom of those things instead of just figuring them out so it works ;o)

Will probably take the route of the single {stash:nocache} pair with setters and getters. Sometimes I feel I am too stuck in my ways of separating logic from display in my templates. I generally code templates with all setters at the top without any HTML and then getters with HTML output (not going the full MVVM route yet).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment