I've been looking at this one due to an interesting question on Stack Overflow: "Confusion in dynamic variable access in ColdFusion". I could not immediately see what the problem was, and it's taken me a coupla hours to work out what's going on.
Here's some code that demonstrates the issue at hand:
key1 = "prefix.key1";
key2 = "prefix.key2";
st = {};
"st.#key1#" = "set via quoted variable name";
st[key2] = "set via associative array notation";
writeDump(st);
writeDump(var=[
{key1=isDefined("st.prefix.key1")},
{key2=isDefined("st.prefix.key2")}
], label="isDefined()");
writeDump(var=[
{prefix=structKeyExists(st, "prefix")},
{"prefix.key1"=structKeyExists(st, "prefix") && structKeyExists(st.prefix, "key1")},
{key1=structKeyExists(st, "prefix.key1")},
{key2=structKeyExists(st, "prefix.key2")}
], label="structKeyExists()");
safe(function(){
writeOutput("st.prefix.key1: #st.prefix.key1#<br>");
});
safe(function(){
writeOutput("st.prefix.key2: #st.prefix.key2#<br>");
});
safe(function(){
writeOutput("st['prefix.key2']: #st['prefix.key2']#<br>");
});
function safe(f){
try {
f();
}catch (any e){
writeOutput("#e.type# #e.message# #e.detail#<br>");
}
}
Here we set to values in a struct: one using erm... dunno what the syntax is call, but the syntax of using a quoted dynamic value as a dynamic variable name; and the other using associative array notation.
Then we output various odds 'n' sods like whether the variable is defined, whether various keys exist, and then the variables' values.
The
safe()
function is just there to de-clutter the code somewhat.And this is the output...
ColdFusion 10 (and lower):
struct | |||||
---|---|---|---|---|---|
prefix |
| ||||
prefix.key2 | undefined |
isDefined() - array | |||||
---|---|---|---|---|---|
1 |
| ||||
2 |
|
structKeyExists() - array | |||||
---|---|---|---|---|---|
1 |
| ||||
2 |
| ||||
3 |
| ||||
4 |
|
st.prefix.key1: set via quoted variable name
Expression Element PREFIX.KEY2 is undefined in ST.
st['prefix.key2']: set via associative array notation
See how the dump can't see the value of the
prefix.key2
key, nor can isDefined()
, and nor can actually outputting it using dot notation.But the value is actually there.
ColdFusion 11 is much the same, except for the dump working properly:
struct | |||||
---|---|---|---|---|---|
prefix |
| ||||
prefix.key2 | set via associative array notation |
And Railo works the same as ColdFusion 11.
Interestingly, if I comment-out this:
"st.#key1#" = "set via quoted variable name";
Then
prefix.key2
is completely visible across the board.The thing is that once there's a substruct called
prefix
created, ColdFusion / Railo gets confused when trying to access prefix.key2
. They decide that it's not a key name, but a reference to a subkey key2
within the prefix
substruct. Which - of course - does not exist.I can see how this happens, but it possibly shouldn't? What do you think?
--
Adam