Skip to content
Mark Croxton edited this page Oct 3, 2013 · 74 revisions

Stash embeds are template files that can be included at different points in the parse order of the host template: at the very start (before template parsing), inline (processed like a template tag), or at the end after normal template parsing has completed (post-processed).

They can be nested, but unlike standard ExpressionEngine embeds you can use pre-parsing to assemble a single compiled cache of the rendered templates - which gives you all the benefits of encapsulation without the overhead.

Non-caching regions of your template code can be demarcated with {stash:nocache}{/stash:nocache} tag pairs so that parts of the compiled template remain dynamic.

Stash embeds can optionally be cached to a static file, for when performance is critical.

Basic examples

{!-- Stash template file at /path/to/stash_templates/test.html --}
{stash:embed name="test"}

{!-- ...or using the short syntax --}
{stash:embed:test}

{!-- Other file types can be embedded by appending the extension to the name --}
{stash:embed name="test.js"}

{!-- Stash variables will be parsed if passed in the name parameter --}
{stash:embed name="{stash:my_var}"}

Context

You can optionally define a namespace for your embed, which should have a corresponding subfolder in the Stash template folder:

{!-- Stash template file at /path/to/stash_templates/foo/bar.html --}
{stash:embed name="foo:bar"}

{!-- could also be written as... --}
{stash:embed context="foo" name="bar"}

{!-- ...or using the shortcut syntax --}
{stash:embed:foo:bar}

The @ pointer

The @ pointer references the current static context. In this example we're using it to embed either a right-aligned or left-aligned layout template depending on the language code in {segment_1}.

{stash:embed name="my_layout" context="@"}

{exp:switchee variable="{segment_1}" parse="inward"}

   {!-- left to right layout for latin languages --}
   {case value="en|fr|it"}
      {!-- template at stash_templates/ltr/my_layout.html --}
      {exp:stash:context name="ltr"}
      {exp:stash:set name="content"}My language specific content{/exp:stash:set}
   {/case}

   {!-- right to left layout for arabic --}
   {case value="ar"}
      {!-- template at stash_templates/rtl/my_layout.html --}
      {exp:stash:context name="rtl"}
      {exp:stash:set name="content"}بلدي محتوى لغة معينة{/exp:stash:set}
   {/case}
{/exp:switchee} 

Note that the embed is included above the conditional that determines the context. That's possible because by default embeds are parsed at the end of template parsing (process="end").

Passing variables to the embed

Variables can be passed as parameters to the embed in the form stash:my_var="value".

{stash:embed:foo:bar stash:my_var1="value" stash:my_var2="value"}

Variables in the embedded template

Native stash variables and variables passed to the embed as parameters can be accessed in the form {stash:my_var}. EE snippets and snippet variables created by Stash (with type="snippet") can be accessed in the form {my_var}. Both can be evaluated in conditionals.

Independent instances of the same template file

If you want to create different cached instances of the same template file, use the file_name parameter to specify the file location:

{stash:embed name"my_var1" file_name="foo:bar" stash:my_var="value 1"}
{stash:embed name"my_var2" file_name="foo:bar" stash:my_var="value 2"}

When using the file_name parameter to reference embeds, you can nest your stash template directories:

{!-- Stash template file at /path/to/stash_templates/foo/bar/another/level.html --}
{stash:embed name"my_var1" file_name="foo:bar:another:level" stash:my_var="value 1"}

The @URI pointer

The @URI pointer is a special context referencing the current page URI. It's very handy when you are caching an embed where the final rendered output has a different value depending on the URL.

{stash:embed name"my_var" context="@URI" file_name="foo:bar"}

Process

By default, Stash embeds are processed at the end of template parsing. The point at which the embed is included in the host template is defined by the process parameter:

process="start"

Embed the template before any other variables and tags in your template are parsed (similar to an EE snippet).

process="inline"

Embed the template in the natural parse order of the template.

process="end"

Embed the template at the end of template parsing after other tags and variables have been parsed.

process="static"

Before ExpressionEngine is even initialised, we check to see if a static cache file exists for the requested URL. If it does it is displayed. If it doesn't, EE is loaded and the template parsed at the end of template processing and saved as a static file. This option is therefore only suitable for full-page caching (where the {stash:embed} is the only tag in the host template), and where you do not need to escape dynamic regions of template code.

Embeds are just Stash variables

Once you have included an embed somewhere in your page, you can retrieve it's content without additional overhead just as you would any other Stash variable - providing the embed is included earlier in the parse order.

{!-- include the embed inline, like a tag, so it can be retrieved by later tags... --}
{stash:embed name="bar" process="inline"}
{exp:stash:get name="bar"}

{!-- ...or tweak the priority value to precisely control the parse order --}
{stash:embed name="bar" process="end" priority="1"}
{exp:stash:get name="bar" process="end" priority="2"}

Parse stage

By default, Stash embeds are rendered on retrieval. That means the cached instance of the embed saved in the database contains your un-parsed template code; this is very similar to how ExpressionEngine embeds work.

To pre-render your Stash embeds so that part or all of the template code is rendered before being saved the first time it is viewed, set the parse_stage parameter:

parse_stage="set"

Parse the template the first time it is read from the file, and cache the rendered result. Subsequent retrievals will return the cached template from the database and not the original template file (unless you have set replace="yes" parameter or have set 'stash_file_sync' = TRUE in your config).

parse_stage="get"

Read the template file and cache it to the database. When output to the template on the first and subsequent retrievals the template will be parsed. This is similar to how EE templates work.

parse_stage="both"

Parse the template before caching AND after it is retrieved. This can be very useful when enclosing regions of your template with {stash:nocache}{/stash:nocache}. On SET the template code inside {stash:nocache} will not be parsed, but everything else will. On GET it will be parsed. This provides a way to partially cache some of your template code while leaving other areas dynamic.

Caching embeds and escaping regions

The following is an example of pre-rendering a full page template but escaping the navigation so it remains dynamic.

EE template at blog/index.html
{stash:embed
    context="@URI"
    name="blog"
    file_name="viewmodels:page_vm"
    parse_stage="both"
    stash:_channel="blog"
    stash:_layout="page"
}
Stash template at viewmodels/page_vm.html
{stash:embed context="layouts" name="{stash:_layout}"}

{exp:switchee variable="{segment_2}" parse="inward"}

    {!-- list entries --}       
    {case value=""}

        {exp:stash:set name="pg_title"}List of Blog entries{/exp:stash:set}

        {exp:stash:set name="pg_content" parse_tags="yes"}
            <ul>
            {exp:channel:entries 
                channel="{stash:_channel}"
                status="open"
            }
                <li><a href="{url_title}">{title}</a></li>
            {/exp:channel:entries}
            </ul>
        {/exp:stash:set}
    {/case}

    {!-- single entry --}
    {case default="yes"}
        {exp:channel:entries 
            channel="{stash:_channel}"
            status="open" 
            limit="1" 
            require_entry="yes"
        }
            {if no_results}
                {redirect="site/404"}
            {/if}

            {!-- set fields --}
            {exp:stash:set type="snippet"}
                {stash:pg_title}{title}{/stash:pg_title}
                {stash:pg_content}{cf_content}{/stash:pg_content}
            {/exp:stash:set}

        {/exp:channel:entries}
    {/case}
{/exp:switchee}
Stash template at layouts/page.html
<!DOCTYPE html>
<html>
    <head>
        <title>{pg_title}</title>
    </head>
    <body>
        <nav>
            <ul>
            {!-- don't cache navigation --}
            {stash:nocache}
                {exp:taxonomy:nav tree_id="1"display_root="no"}
                <li><a href="{node_url}">{node_title}</a></li>
                {/exp:taxonomy:nav}
            {/stash:nocache}
            </ul>
        </nav>

        <div role="main">
            {pg_content}
        </div>

    </body>
</html>

Cache a Stash embed to a static file

Static caching can be enabled by passing the process="static" parameter to the embed. Note that all template code will be rendered and cached, we cannot keep regions dynamic.

{stash:embed
    context="@URI"
    name="page_vm"
    file_name="viewmodels:page"
    process="static"
}
Clone this wiki locally