ExpressionEngine CMS
Open, Free, Amazing

Thread

This is an archived forum and the content is probably no longer relevant, but is provided here for posterity.

The active forums are here.

assigned variable changes content in some context

July 14, 2008 5:23pm

Subscribe [0]
  • #1 / Jul 14, 2008 5:23pm

    eexperience's avatar

    eexperience

    56 posts

    Hi,
    I’ve got a weird problem where EE is changing the output of a variable during parsing. I’m trying to generate a Google Sitemap XML file.

    I’ve assigned a variable at the top of my xml file.

    {assign_variable:lastmodDate="{exp:stats}{last_entry_date format='{DATE_W3C}'}{/exp:stats}"}

    Which works fine with:

    <url>
    <loc>http://www.example.com/examplegroup/template/C11/</loc>
    <lastmod>{lastmodDate}</lastmod>
    <changefreq>weekly</changefreq>
    1.0</priority>
    </url>

    which outputs:

    <url>
    <loc>http://www.example.com/examplegroup/template/C11/</loc>
    <lastmod>2008-07-12T17:57:26+01:00</lastmod>
    <changefreq>weekly</changefreq>
    1.0</priority>
    </url>

    But with the following it gets weird:

    {exp:weblog:categories weblog="eintraege" show_empty="yes" style="linear" category_group="4" disable="categories|member_data|pagination|trackbacks"}{if type != "level1Heading"}
    <url>
    <loc>{site_url}examplegroup/template/C4/tag/<?php echo(rawurlencode("{category_name}"));?></loc>
    <lastmod>{lastmodDate}</lastmod>
    <changefreq>weekly</changefreq>
    0.5</priority>
    </url>
    {/if}{/exp:weblog:categories}

    output is:

    <url>
    −
    <loc>
    <a href="http://www.example.com/examplegroup/template/C4/tag/Hotels">http://www.example.com/examplegroup/template/C4/tag/Hotels</a> & Motels
    </loc>
    <lastmod>M00o93H7pQ09L8X1t49cHY01Z5j4TT91fGfr</lastmod>
    <changefreq>weekly</changefreq>
    0.5</priority>
    </url>

    PHP parsing is set to output stage. Though I checked by removing the php-statement and the error still occurs. Why could the variable {lastmodDate} change it’s content to “M00o93H7pQ09L8X1t49cHY01Z5j4TT91fGfr”?

  • #2 / Jul 14, 2008 5:27pm

    Ingmar's avatar

    Ingmar

    29245 posts

    What version and build are you on? I’ve seen this error a few times, and quite often it simply boiled down to file corruption. Might want to re-upload your files, perhaps updating to the latest build in the process.

  • #3 / Jul 14, 2008 5:34pm

    eexperience's avatar

    eexperience

    56 posts

    Hi Ingmar,
    I’m using ExpressionEngine 1.6.4, Build: 20080710

    The weird thing is, that this happens all in the same XML file.

  • #4 / Jul 14, 2008 5:47pm

    eexperience's avatar

    eexperience

    56 posts

    I’ve reuploaded all files mentioned in the EE Documentation for updating to the latest version, just in case. The problem still persists.

  • #5 / Jul 14, 2008 6:18pm

    Justin Hurlburt's avatar

    Justin Hurlburt

    344 posts

    Greetings,

    It seems that assign_variable doesn’t like nested variables in the declaration. A workaround for right now is to just use the format instead of a variable for lastmodDate.

    {assign_variable:lastmodDate="{exp:stats}{last_entry_date format='%Y-%m-%dT%H:%i:%s%Q'}{/exp:stats}"}

    I’ll be looking into why nested variable declarations are not functioning correctly.

  • #6 / Jul 14, 2008 6:29pm

    eexperience's avatar

    eexperience

    56 posts

    I just tried your code, cleared all caches, still the same weird output.

    It outputs <lastmod>2008-07-01T16:04:00+01:00</lastmod> if I just use {lastmodDate} but if I wrap it inside the {exp:weblog:categories} I get <lastmod>M00o93H7pQ09L8X1t49cHY01Z5j4TT91fGfr</lastmod>

  • #7 / Jul 14, 2008 8:03pm

    Justin Hurlburt's avatar

    Justin Hurlburt

    344 posts

    It seems I over-looked the parsing order. Your solution is embeds I believe.

  • #8 / Jul 15, 2008 5:21am

    eexperience's avatar

    eexperience

    56 posts

    Justin, I think we’re on the wrong track with this. I can even skip the assigned variable bit and just put the {exp:stats}{last_entry_date format='%Y-%m-%dT%H:%i:%s%Q'}{/exp:stats} line everywhere I need it. The results are the same. Which is even more odd, since I thought that an assigned variable gets evaluated just once and then the content of it gets echoed wherever I put the variable name. But the output changes whenever I put the {exp:stats} call or the variable inside the {exp:weblog:categories}. I assigned the variable outside of this loop at the top of the XML file.

    Even this code outputs the correct date as long as I stay outside of {exp:weblog:categories}, that’s why I assigned a variable for the {exp:stats} in the first place. Because I was assuming that {exp:stats} had something weird going on inside the {exp:weblog:categories}. So I tried assigning a variable, which I thought would just echo the string.

    Why would “2008-07-01T16:04:00+01:00” change to “M00o93H7pQ09L8X1t49cHY01Z5j4TT91fGfr” just because it’s output inside {exp:weblog:categories}?

  • #9 / Jul 15, 2008 3:21pm

    Justin Hurlburt's avatar

    Justin Hurlburt

    344 posts

    Greetings,

    Embeds would solve this, as each template is parsed on it’s own. The reason we need this is that each tag is identified in the order it occurs in the template. The tag is then stored in an array, and replaced with a temporary marker. The template is then parsed and the tags marker is replaced with the corresponding $return_data. If an identical tag occurs more than once in a template, the copy is replaced with the same marker. The second digit in the marker is the index in the array of tags (i.e.: M0…, M1…, M2… etc). After the tag is parsed, the markers are replaced.

    Since 0 comes before 1, and there’s a marker for 0 (lastmodDate) inside of the maker for 1 (weblog:entries), the marker doesn’t get replaced when tag 0 is parsed. Tag 0’s code is never executed again, so the marker 0 (lastmodDate) that was inside of marker 1 (weblog:entries) never has an opportunity to be replaced by anything. So you end up with the temp marker output. Embeds allow each template to be parsed separately, and would solve this issue.

  • #10 / Jul 15, 2008 3:31pm

    eexperience's avatar

    eexperience

    56 posts

    And why does even a direct {exp:stats}{last_entry_date format=’%Y-%m-%dT%H:%i:%s%Q’}{/exp:stats} result in the same output when it’s executed inside a {exp:weblog:categories}?

  • #11 / Jul 15, 2008 3:40pm

    Derek Jones's avatar

    Derek Jones

    7561 posts

    The assign variable tag is immaterial here, as you have just surmised.

    The template parser is an extremely complex gizmo, so let me try to explain it stripped of what techno mumbo jumbo I can. This will still be long, so bear with me.

    The template parser intelligently saves on resources by only processing a given tag once, no matter how many times it occurs on the template.  This means that if your tag is exactly the same, including its tagdata, EE only execute’s that modules code once, and replaces all copies of that tag with the output.

    So first, when the template parser goes through the template finding tags, it replaces them all with temporary markers (the gibberish), and adds each tag to a list of tags to be parsed, in the order they are encountered on the template, top down.  Each marker starts with the letter “M” followed by the number (starting at 0) that tag is sitting in on The List.

    Second, the parser goes down its list of tags.  It parses tag #0, and then replaces all of #0’s marker with that tag’s output.

    ——————-

    Ok that’s the setup.  Here’s why it affected you, and why this side effect is not a problem (and also extremely, extremely rare). Remember, top down, tags will be assigned 0, 1, 2, etc.  So I’m abstracting it out to show the nesting and the positioning only.  Just focus on the numbers.

    {exp:tag0}foo{/exp:tag0}
    {exp:tag1}
        bar
        {exp:tag0}foo{/exp:tag0}
    {/exp:tag1}

    Step 1, the tags are grabbed and replaced with markers.  The first tag encountered is replaced first.

    M0
    {exp:tag1}
        bar
        M0
    {/exp:tag1}

    And then the next tag:

    M0
    M1

    All tags have been collected and put on The List, so step 2, the parser goes down The List, and parses tag #0:

    foo
    M1

    See the problem?  The second M0 is sitting protected inside the marker for tag #1, so it doesn’t get replaced.  Then tag #1 gets parsed.

    foo
        bar
        M0

    And the marker is left in the output.  EE doesn’t go back and parse tag #0 again, it’s already done that once, and will not do it again.

    So the circumstances required for this problem to exist each are uncommon, and combined, very very rare:

    1) Multiple exact copies of a given tag
    2) One or more copies nested inside another tag (tag nesting itself is also rare, and usually not recommended)
    3) The tag of which there are copies must sit at a position in the template above any occurrences of it being nested in another tag.

  • #12 / Jul 15, 2008 6:04pm

    eexperience's avatar

    eexperience

    56 posts

    Thanks a lot Justin and Derek for your explanation. It really makes a difference for me in understanding Expression Engine at its core. This is the stuff I want to know, so thanks for taking the time to show me what’s under the hood. You should do a few podcasts/videocasts on such things. I would really appreciate it, since it would help us to understand the way EE is meant to work.

    The only thing I still don’t understand, why’s there such gibberish like “M00o93H7pQ09L8X1t49cHY01Z5j4TT91fGfr” in the output. Shouldn’t there be just nothing instead? At least that’s what I’m used to from EE, when there’s a any parsing problem, EE stays silent in the output.

    Thanks again for your detailed posts, it really helps.

  • #13 / Jul 15, 2008 6:34pm

    Derek Jones's avatar

    Derek Jones

    7561 posts

    This particular scenario is just something that the template parser was not designed to anticipate.  It’s not intentional that it leaves the unparsed markers, I think for me at least, this is the first that I’ve ever seen it occur.  I think armed with this knowledge, we can take steps in future versions to find and remove these, and make a note in the Template Parsing log that so Super Admins can still have some feedback to know that something went wrong.  Confusing as it was to you, its existence in the output did prompt you to come here and post for help, which might not have occurred (or have been as easily diagnosable on our end) if it was silent.

  • #14 / Jul 16, 2008 8:01am

    eexperience's avatar

    eexperience

    56 posts

    You guys should definitely do a screencast series to explain best coding practices and how EE is designed to work internally. It’s only now that I realize that I’m seeing the marker definition. I really see the need for people who want to really grasp building complex sites in EE. There are so many things you can combine and nest and put conditionals in that you should explain how to make the most out of EE and not interfere with the logic that EE was built by. It doesn’t have to be a well laid out cleaned up tutorial series, just some quick sessions to enhance our knowledge about EE.

  • #15 / Jul 16, 2008 10:56am

    eexperience's avatar

    eexperience

    56 posts

    Just wanted to add that everything now works as expected. It feels so much better when you know about the mechanics and to know what results to expect instead of just working with trial and error. Thanks for your help!

.(JavaScript must be enabled to view this email address)

ExpressionEngine News!

#eecms, #events, #releases