StructGet not Working Correctly for Scalar Variables in CF 9?
Copy link to clipboard
Copied
In ColdFusion 9, the following code snippet:
<cfset x = "5">
<cfset y = StructGet("x")>
<cfoutput>isStruct(y) = #isStruct(y)#<br></cfoutput>
<cfoutput>y = <br></cfoutput><cfdump var = "#y#"><cfoutput><br></cfoutput>
returns:
isStruct(y) = NO
y =
5
even though the CF documentation states that "if you accidentally use this function on a variable that is not a structure, it replaces the value with an empty structure" (see http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSc3ff6d0ea77859461172e0811cbec22c24-6210.html).
Under ColdFusion 8, the above code snippet does set up y as a structure.
Am I doing something wrong in the above code snippet, or is this a bug in ColdFusion 9?
Copy link to clipboard
Copied
The way I understand it, structget() represents a deeply nested structure as a simpler one. In the following example, the structure z.y.x.w is represented simply as the structure w.
It implies that w.v is shorthand for z.y.x.w.v. The value of z.y.x.w.v is therefore 5.
<cfset w = StructGet("z.y.x.w")>
<cfset w.v = "5">
<cfoutput>isStruct(w) = #isStruct(w)#</cfoutput><br>
<cfoutput>isStruct(z.y.x.w) = #isStruct(z.y.x.w)#</cfoutput><br><br>
z.y.x.w.v = <cfoutput>#z.y.x.w.v#</cfoutput>
Copy link to clipboard
Copied
My question is whether or not StructGet in ColdFusion 9 is working correctly with scalar variables. That is, my application employs the Spectra content management system, and buried inside of such custom tags as cfa_contentObjectGet and cfa_contentObjectCreate are statements of the form
<cfset stEmbeddedObject = StructGet("stObject.#scope#")>
where the scope variable contains the name of one of the properties in the stObject structure. In ColdFusion 8, no matter what scope referred to, stEmbeddedObject would be a structure; in ColdFusion 9, if scope refers to a scalar variable, stEmbeddedObject ends up being a scalar variable, not a structure (and thus subsequent statements that treat stEmbeddedObject as a structure blow up).
Copy link to clipboard
Copied
in ColdFusion 9, if scope refers to a scalar variable, stEmbeddedObject
ends up being a scalar variable, not a structure (and thus subsequent
statements that treat stEmbeddedObject as a structure blow up).
Not quite true. When I run the following in Coldfusion 9, it displays Yes
<cfset scope= 5>
<cfset stEmbeddedObject = StructGet("stObject.#scope#")>
<cfoutput>#isStruct(stEmbeddedObject)#</cfoutput>
However, the documentation on structGet warns you on several occasions that Coldfusion does its best to store the return-variable of the function as a struct. In other words, Coldfusion takes your word that the argument of the function is a valid struct. It is your responsibility to make sure it is.
For example, even though Coldfusion tells you stEmbeddedObject is a struct, the code will bomb if you tried to use it as such. That is because stObject.5 isn't a valid structure. In my opinion, StructGet's assignment of stEmbeddedObject to a struct happens at compile time. Coldfusion makes no guarantees at runtime.
Copy link to clipboard
Copied
My mistake on not providing an example of what I meant by the phrase "scope refers to a scalar variable".
Consider the following code snippet:
<cfset x = StructNew()>
<cfset x["age"] = 35>
<cfset x["firstname"] = "Maxwell">
<cfset x["lastname"] = "Smart">
<cfset x["address"] = StructNew()>
<cfset x["address"]["street"] = "123 Main Street">
<cfset x["address"]["city"] = "Washington">
<cfset x["address"]["state"] = "DC">
<cfset x["address"]["zipcode"] = "20000">
<cfset scope = "age">
<cfset myage = StructGet("x.#scope#")>
<cfoutput>isStruct(myage) = #isStruct(myage)#<br></cfoutput>
<cfoutput>myage = <br></cfoutput><cfdump var = "#myage#"><cfoutput><br></cfoutput>
returns
isStruct(myage) = NO
myage =
35
in ColdFusion 9, but it returns
isStruct(myage) = YES
myage =
struct[empty]
in ColdFusion 8.
The documentation on structGet does not mention anything about this change in behavior from ColdFusion 8 to ColdFusion 9, thus leading me to believe that either:
1. structGet in ColdFusion 9 is not working correctly (and thus the reason for my original posting in this forum)
- or -
2. The documentation for structGet in ColdFusion 9 should be updated to note this change in behavior from previous versions (at least all the way back to version 4.x) of ColdFusion.
Copy link to clipboard
Copied
Consider the following code snippet:
<cfset x = StructNew()>
<cfset x["age"] = 35>
<cfset x["firstname"] = "Maxwell">
<cfset x["lastname"] = "Smart">
<cfset x["address"] = StructNew()>
<cfset x["address"]["street"] = "123 Main Street">
<cfset x["address"]["city"] = "Washington">
<cfset x["address"]["state"] = "DC">
<cfset x["address"]["zipcode"] = "20000"><cfset scope = "age">
<cfset myage = StructGet("x.#scope#")>
<cfoutput>isStruct(myage) = #isStruct(myage)#<br></cfoutput>
<cfoutput>myage = <br></cfoutput><cfdump var = "#myage#"><cfoutput><br></cfoutput>returns
isStruct(myage) = NO
myage =
35
in ColdFusion 9, but it returns
isStruct(myage) = YES
myage =
struct[empty]
in ColdFusion 8.
Strange. I have Coldfusion 9, too. When I run your code I get:
isStruct(myage) = YES
myage =
struct[empty]
But then, there might be a difference in build number. I am on Coldusion 9.0.0.241018.
This following is a little ambiguous:
<cfset scope = "age">
<cfset myage = StructGet("x.#scope#")>
You should compare like with like. The struct x["age"] is the same as x.age. The code for a better comparison would therefore be:
<cfset scope = "age">
<cfset xAge = "x." & scope>
<cfset myage = StructGet(xAge)>
Copy link to clipboard
Copied
I am running ColdFusion Developer version 9.0.0.251028 under Microsoft Windows Server 2003 R2 Enterprise Edition.
As for the actual code using the StructGet function, as I mentioned before this was written by the developers of Spectra in the early 2000's, not by me. I have patched the following Spectra code fragment:
<!--- get the handle to the embedded object --->
<cfset stEmbeddedObject = StructGet( "stOwnerObject.#scope#" )>
by adding the following right after it:
<cfif not isStruct(stEmbeddedObject)>
<cfset stEmbeddedObject = StructNew()>
<cfset "stOwnerObject.#scope#" = stEmbeddedObject>
</cfif>
which I believe mimics what the StructGet function in ColdFusion 8 was doing. Of course, what I really want is for ColdFusion 9 to behave the exact way as ColdFusion 8 when it comes to the StructGet function, hence the reason for my original posting in this forum.
I guess the next thing to do is to find out how to submit a discrepancy report to Adobe, requesting that they either fix the StructGet function in ColdFusion 9 or update the documentation to inform people that it doesn't behave the same way as it did for ColdFusion 8. Or, perhaps they've already released a new version of ColdFusion 9 in which StructGet works correctly?

