3

I boiled my problem down to this template code on a template with "Allow PHP" set to "YES" and "PHP Parsing Stage" set to "Output":

{if 1 == 1}
  First block
  <?php echo '1 == 1 is true'; ?>
  <?php $test = 'hello'; ?>
{if:else}
  Second block
  <?php echo '1 == 1 is false'; ?>
  <?php $test = 'goodbye'; ?>
{/if}
<?php echo $test; ?>

The output is:

First block
1 == 1 is true
goodbye

But I would expect the output to be:

First block
1 == 1 is true
hello

I don't understand how the 1 == 1 is true line could get echoed while the variable $test gets set to "goodbye". It seems like my PHP variable assignments statements all get executed whether or not the conditional block they are in should get executed or not.

Update

This is apparently still a problem even when I eliminate the PHP from the template:

{if 1 == 1}
  1 == 1 is true
  {exp:stash:set name="test"}hello{/exp:stash:set}
{if:else}
  1 == 1 is false
  {exp:stash:set name="test"}goodbye{/exp:stash:set}
{/if}
{exp:stash:test}

The output is:

1 == 1 is true
goodbye

3 Answers 3

3

That's Parse Order. Advanced conditionals, like the one in your example, are parsed after PHP is parsed. In fact, it doesn't even matter if PHP is set on Output or Input. So, think of this step by step. First, your PHP is executed, echoing both 1 == 1 is true and 1 == 1 is false. And the var $test is first set to hello, then to goodbye, after which the latter is echoed out.

Then the advanced conditional is parsed, hiding the first block. But the setting and echoing of $test has already been done, hence goodbye remains as is.

'Tis the nature of EE's Parse Order Beast.

4
  • Well, that is unfortunate. So much for "don't repeat yourself" if I can't use PHP variables for most of what I'm doing. :-/ Thank you, though! #ReasonsILikeMovableType Apr 16, 2013 at 8:03
  • Note I have expanded the question somewhat as I have since discovered the exact same behavior with Stash alone, and I am not sure it should be a separate question since the results are identical. Apr 16, 2013 at 8:41
  • Same principle applies. The tags are parsed before the advanced conditionals, thus always setting the Stash var test to goodbye. Either use simple conditionals or another Croxton plugin like IfElse or Switchee to not rely on advanced conditionals like this.
    – Low
    Apr 16, 2013 at 9:02
  • Ah, I didn't see the implication for template tag parsing in general... this is quite annoying and counterintuitive! Apr 16, 2013 at 9:07
1

Following on from @Low's answer and your comment, it doesn't mean that you can't still use PHP successfully in templates. You just need to be mindful of the parse order when mixing PHP with EE tags.

For instance in your example if you used PHP for the full if statement then it would work as it would all be parsed at the same time from top to bottom.

Alternatively use something like Stash to set variables and then call them later in your template in among regular EE tags. You'll then be on par with the parse order again.

You can see a couple of examples of mixing PHP with EE tags on both input and output here.

As a good rule of thumb though try to keep PHP use in your templates down as much as possible for security...and sanity in regards to parse order. ;)

5
  • Please see the update to my question. I am seeing exactly the same behavior when I eliminate the PHP entirely and use Stash variables instead. Is this as expected? Further, I can't use PHP fully, either, since in my actual code, the conditional is testing EE fields. Apr 16, 2013 at 8:38
  • Look to use {exp:stash:parse process="end"} to take control of the parse order of your Stash variables. You may also set a priority on this tag.
    – Ian Young
    Apr 16, 2013 at 9:05
  • Thank you, I think I've got a solution working using more PHP and less EE... which seems to be more reliable of a strategy in general. ;-) Apr 16, 2013 at 9:08
  • 1
    There's always another way. ;) EE doesn't try and lock you down so you have the flexibility to go with what feels comfortable and the good thing is that there's always more than one way to do it. Generally though it's always best practice in modern web dev to keep those templates logic-less (ala mustache) so one step up is to abstract your PHP to a simple plugin then you can create your own EE tag(s) to use in your templates.
    – Ian Young
    Apr 16, 2013 at 11:51
  • Stash should also do the job but all of these things just take some getting used to. Remember it's a strength following best practices rather than a weakness however.
    – Ian Young
    Apr 16, 2013 at 11:53
1

You can easily resolve parse issues like these with Switchee or Ifelse. These addons will completely remove any non-matching conditions before they are parsed. Here's how you'd fix the code sample from your post:

{exp:ifelse parse="inward"}
    {if 1 == 1}
        1 == 1 is true
        {exp:stash:set name="test"}hello{/exp:stash:set}
    {if:else}
        1 == 1 is false
        {exp:stash:set name="test"}goodbye{/exp:stash:set}
    {/if}
    {exp:stash:test}
{/exp:ifelse}

This template will output 1 == 1 is true hello as expected.

The parse="inward" parameter is key - it tells EE to parse the outer tag (the IfElse plugin) before processing the inner ones (the stash:set calls). See the EE docs for further info.

1
  • Thanks, I need to avoid more plugins. This installation already has enough buggy behavior without my adding more complexity! It's a shame EE templating doesn't operate intuitively with the core product. Apr 16, 2013 at 17:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.