I’ve had a chance to be involved in some some pretty fun and exciting ExpressionEngine projects lately. Often, this means looking through sites that other developers had originally built out. Its always fun seeing how other smart people choose to solve a problem - often in a different way then I’d do it. Reading other people’s code is always a great way to learn.
That said, a recurring theme I see are poorly optimized EE templates. Usually, there are minor changes I can have a dramatic impact. The most common minor fix is simply understanding the difference between “simple” and “complex” conditionals. While digging around for a few good resources I could use to help explain it, I stumbled across a wonderful post on the EE forums by John D Wells that explains it masterfully, which I’m reposting here with his permission for my convenience. As an aside, John is a pretty prolific guy, and if you aren’t subscribed to his blog, now is a good time to check it out.
At last night’s LondonEErs Meetup, we got into a brief talk about Simple vs. Complex Conditionals. This level of black-hat-trickery was new to me, but of interest as I try to optimise a particularly sluggish site, so I decided to look into it.
Online documentation about this is minimal, with only a few quality sources that lay things out clearly (listed at bottom). For the sake of summary, and to allow the rest of my LondonEErs (and others!) to discuss, here’s my take on it all…
Parse order matters
We’re ultimately talking about parse order here: at which point does EE’s parsing engine do what, and how that might effect performance. For a handy-dandy PDF outlining EE’s parse order, check out Low’s PDF breakdown:
The simplified list is as follows:
- Parse snippets / global variables, segment variables and embed variables
- Parse PHP on Input
- Parse simple conditionals: segment, embed, global variables
- Assign and parse preload_replace variables
- Parse module and plugin tags
- Parse PHP on Output
- Parse advanced conditionals
- Process embedded templates
- Parse User Defined global variables and others
* Refer to Low’s PDF regarding specific parse order nuances between EE1x and EE2.
EE’s 2 types of conditionals
So, EE parses two types of conditionals at different stages in the parse process: Simple vs Complex. Simple conditionals are parsed early, before any module or plugin tags are parsed. Complex conditionals on the other hand are processed late in the game, after things like module or plugin tags.
The performance impact is potentially substantial: as an example if you have two different exp:weblog:entries tags within a template, where only one of the two should be processed based on a Complex conditional evaluation, they will in fact both be parsed, but only one will be output.
That’s a big deal. So we need to clearly understand what specifically constitutes what.
EE considers a conditional to be “Simple” IF AND ONLY IF:
-it contains no if/else sort of logic switching
-it does not use AND, OR, XOR, etc operators
-it ONLY works with segment, embed, or global variables
Last point is crucial: If you’re conditional operates on any other variable, e.g. an entry status, category, member info etc, then it will be considered COMPLEX, and parsed further down the parse chain.
So it’s an over-simplification to suggest that an if:else is inherently bad (as was discussed last night): it’s only bad if you’re using an if:else within a conditional that would otherwise be considered Simple.
Can PHP help?
Not really. As we know, PHP can be processed in templates, and at two different stages in the parsing chain: on “input” and on “output”. Take a look once more at the ordered list above to see how this stacks up.
What we find is that parsing PHP on “input” only helps if you want to use if:else switches, and AND/OR etc operators, upon ONLY those variables that are available early on (segment, global and embed variables).
However if you want to perform a PHP-based conditional upon any other type of variable, you have to parse on “output”, which means coming after the parse stage where module and plugin tags are parsed. It will not save you from the overhead of over-parsing.
Before you panic that all of your if:else statements are Complex and therefore being dutifully overly-parsed by EE, there is one possible saviour here: Embeds. While an embed comes with it’s own downfalls of overhead, they are at least parsed after Complex conditionals.
So if you’re trying to avoid having EE parse and process everything contained within Complex conditionals, your only resort is to use embeds.
I’ll leave it to you to determine whether you should. :)
In addition to Low’s PDF mentioned above, here are three more resources that helped me get started:
Lodewijk Schutte’s presentation titled, “PHP in templates: Pain or Pleasure”: http://slidesha.re/cORsRa
Low’s aforementioned PDF, “EE’s Parse Order”: http://bit.ly/ajZ5s9
“Performance Guidelines” PDF, from Solspace’s Paul Burdick: http://bit.ly/dbKx4r
“EE & High Traffic Sites” PPT, from Grist’s Matt Perry: http://bit.ly/c7tqzU