Conditional Blocks in Partials

12th June 2015

Tip

If you’re using a partial multiple times on a single page, keep the number of conditional code blocks within that partial to a minimum.

Rationale

We all love partials. You know, those things where in your theme where you just call:

{{ theme:partial src="mypartialname" }}

But if you’re going to place them in a pages:listing or entries:listing and break out their functionality into smaller pieces that are lovely and modular that’s fine, until you end up with dozens of iterations of that partial on the page.

That’s the point though isn’t it? Well…yes. But the trap is to try and have a "god-partial" that is essentially an overloaded function that does layout for every flavour of that partial there is. Seems like it could be a good idea - you know - keep all of that object code in one place right? Well…no.

What am I jibbering on about? An example: (OPTION A)

{{ if { fileexists file=_myfile } }}<img src="{{ _myfile }}" alt="{{ name }}">
{{ else }}<img src="/assets/_myfile" alt="{{ name }}">
{{ endif }}
<div class="mytablelinks">
    {{ if _twitter|_facebook|_linkedin|_website }}<center>{{ endif }}
    {{ if _twitter }}<a href="https://twitter.com/{{ _twitter }}" title="{{ name }} on Twitter"><i style="font-size:38px;" class="fa fa-twitter-square"></i></a>{{ endif }}
    {{ if _facebook }}<a href="{{ _facebook }}" title="{{ name }} on Facebook"><i style="font-size:38px;" class="fa fa-facebook-square"></i></a>{{ endif }}
    {{ if _linkedin }}<a href="{{ _linkedin }}" title="{{ name }} on LinkedIn"><i style="font-size:38px;" class="fa fa-linkedin-square"></i></a>{{ endif }}
    {{ if _website }}<a href="{{ _website }}" title="{{ name }}'s Website"><i style="font-size:38px;" class="fa fa-globe"></i></a>{{ endif }}
    {{ if _twitter|_facebook|_linkedin|_website }}</center><hr class="mytable">{{ endif }}
    {{ content }}
</div>
{{ if false }}
    {{ mymeld:people person="{ name }" }}
        {{ if first }}
            <div>
                <hr class="peopletable">{{ total_results }} episode{{ if total_results > 1 }}s{{ endif }}:<br>
        {{ endif }}
        <a href="{{ url }}">{{ segment_1|title }} {{ title }}</a>{{ if !last }}<br>{{ endif }}
        {{ if last }}
            </div>
        {{ endif }}
    {{ /mymeld:people }}
{{ endif }}

Okay so that looks alright enough until we try to get clever like below (and I’m not repeating all that code again): (OPTION B)

{{ if condition="firstflavour" }}
    {{ if { fileexists file=_myfile } }}<img src="{{ _myfile }}" alt="{{ name }}">
    {{ else }}<img src="/assets/_myfile" alt="{{ name }}">
    {{ endif }}
    <div class="mytablelinks">
        BLAH BLAH THE CODE UP THERE BLAH BLAH YOU'VE SEEN IT ALREADY    
    </div>
    {{ if false }}
        {{ mymeld:people person="{ name }" }}
            MORE BLAH BLAH CODE YEAH WHATEVER
        {{ /mymeld:people }}
    {{ endif }}
{{ endif }}

{{ if condition="secondflavour" }}
    MOSTLY THE SAME AS ABOVE BUT WITH TWEAKS HERE AND THERE YOU KNOW BUT USING SAME VARIABLES
{{ endif }}

{{ if condition="thirdflavour" }}
    MOSTLY THE SAME AS THE 2ND ONE BUT WITH MORE TWEAKS HERE AND THERE YOU KNOW BUT USING SAME VARIABLES
{{ endif }}

The performance difference on a server will be better (you’d hope under moderate load conditions for page regeneration) but measured on my 2012 MacBook Air i7 2GHz running MAMP with a zippy SSD the improvement in rendering time from Option A to Option B was…

  • Option B: 28.7sec
  • Option A: 2.4sec
  • 26.3 SECONDS FASTER

The ulimate solution was to split the flavours into three partial themes and the code is no longer in one place.

So instead of this…

{{ theme:partial src="mypartialname" condition="firstflavour" }}
{{ theme:partial src="mypartialname" condition="secondflavour" }}
{{ theme:partial src="mypartialname" condition="thirdflavour" }}

…it looks like this instead:

{{ theme:partial src="mypartialnamefirstflavour" }}
{{ theme:partial src="mypartialnamesecondflavour" }}
{{ theme:partial src="mypartialnamethirdflavour" }}

The lesson is, only call what you need to call in your partial and keep the logic as straight-forward as you can. Unless you want to write your own PHP Addon, which can save even more time depending on what you’re trying to accomplish.

Thanks To

The Statamic Debug Panel only introduced in v1.7.9 as it allowed me to track down the performance suckers in my website.