Design issue xen:set doesn't work with mapped variables

refael

Well-known member
If you map a variable into template,
For example
PHP:
<xen:include template="message">
    <xen:map from="$post" to="$message" />
</xen:include>

Now in template 'message' you will use xen:set
PHP:
<xen:set var="$message.test">123</xen:set>

This seems not to work, if you'll print {$message.test} you'll see it's null.
 
So this is a tricky issue. Changing this behavior can create a different unexpected behavior. I will say that setting an array key generally isn't the expected approach to things and is where this confusion is based. I can't remove that for backwards compatibility reasons though.

When you include a template, it's literally brought into the parent template when compiling. When you map a variable, you're not creating an alias. Let's just say it's called $parent in the parent template and $child in the child template. When you include child and map between those variables, we actually change change $child to $parent during compilation.

Right now, set tags ignore mappings (as do a few other places where variables are created, like foreach). If I allow set to respect mappings, then a $child.test reference will become $parent.test reference and work. Right now, it sets a $child.test value which is "covered" by the mapping in other usages.

However, if I do this there's a way to create further weirdness. If I map $parent to $child1 and $child2 and then use the set tag (with the changes to fix this bug report) to overwrite $child2, it actually overwrites $parent and thus implicitly $child1. This has a knock on effect not only within the child template (via $child1) but within the parent template (the change to support this would change the parent template as well).

Ultimately this relates to the design of including templates, so nothing big can change here at this point. Both approaches here create unexpected behaviors in certain scenarios. I'm not sure which is worse. This situation can be worked around by simply writing into a different variable in all cases, one that isn't mapped. But it also creates a situation that works sometimes and fails other times (I suppose the alternative would have that issue as well, but in different cases).
 
Thanks for the explanation, makes sense.

In general, in most cases you can just set a new variable instead addind a new array value.

It could be a real issue only on complicated cases, where you need to pass the mapped variable into anothe template. In this case you may need to manipulate the array specifically.
This is a case I never tested though.
 
At this point, given all the history, I think it's safer to keep it as is for now. Maybe we'll see a change in the future, but I suspect it would be a 2.0-level of change (to the underlying system).
 
Back
Top Bottom