Dynamic ColdFusion Variables Via Quoted Naming
Posted July 20, 2006 at 8:18 AM
I just came across something very interesting that I have never ever seen before: the creation of dynamic ColdFusion variables via quotes naming. In the past, I have made dynamic variable references using either the Structure-key notation, or if all else fails, the evaluate method.
Launch code in new window » Download code as text file »
- <!--- Create three variables. --->
- <cfset Girl1 = "not sexy" />
- <cfset Girl2 = "not sexy" />
- <cfset Girl3 = "not sexy" />
-
- <!--- Loop over the girls and alter the values. --->
- <cfloop index="intGirl" from="1" to="3">
-
- <!--- Randomly pick 1 (true) or 0 (false). --->
- <cfif RandRange( 0, 1 )>
-
- <!--- Set the dynamic variable naming via struct notation. --->
- <cfset VARIABLES[ "Girl" & intGirl ] = "super sexy" />
-
- <cfelse>
-
- <!--- Set the dynamic variable naming via Evaluate(). --->
- <cfset Evaluate( "Girl#intGirl# = 'mad ugly'" ) />
-
- </cfif>
-
- </cfloop>
Note: I am a huge fan of scoping almost all my variables and therefore use the structure-key notation for dynamic naming as much as possible. I always view the use of Evaluate() as a sort of cop-out of quick fix for poor planning.
But anyway, back on topic, I just found out that you can create dynamic variable names via quotes:
Launch code in new window » Download code as text file »
- <cfset "some_var_name_here" = "some_value" />
I have never seen quoted values on the left side of an equation before. It doesn't even seem like it would work. But is does! This is how this would look in the above example:
Launch code in new window » Download code as text file »
- <!--- Loop over the girls and alter the values. --->
- <cfloop index="intGirl" from="1" to="3">
-
- <!--- Randomly pick 1 (true) or 0 (false). --->
- <cfif RandRange( 0, 1 )>
-
- <!--- Set the dynamic variable naming used quoted evaluation. --->
- <cfset "Girl#intGirl#" = "super sexy" />
-
- </cfif>
-
- </cfloop>
In that example "Girl#intGirl#" creates the proper variable name reference the proper variable. I suppose this is some sort of evaluation... I am not completely sure how it works as to me, the left side should just evaluate to a string, not a variable reference. Anyway, it's kind of interesting to know that this is even possible in ColdFusion. Not sure if I would ever use it.
If you care about speed testing, on my server, neither were consistent. Sometimes one was faster than the other, sometimes it was the other way. Both are fast though.
Download Code Snippet ZIP File
Post Comment | Ask Ben | Other Searches | Print Page
Newer Post
The '..' Characters Are Not Allowed In The Path Parameter For The MapPath Method
Older Post
Ask Ben: Processing A Query In Java
Reader Comments
I am looking for a way to do exactly this in JavaScript. Any ideas?
Marc,
You can do refer to variables in the top level scope using the THIS object, which can refer to different things at different times. Look at this:
// Set up three girls.
var strGirl1 = "sarah";
var strGirl2 = "anne";
var strGirl3 = "christina";
// Set dynamic variable.
this[ "strGirl" + 2 ] = "kimmie";
// Alert three girls.
alert( strGirl1 );
alert( strGirl2 );
alert( strGirl3 );
function Test(){
// Set up three girls.
var strGirl1 = "fn - julia";
var strGirl2 = "fn - alex";
var strGirl3 = "fn - maggie";
// Set dynamic variable.
this[ "strGirl" + 2 ] = "fn - connie";
// Alert three girls.
alert( strGirl1 );
alert( strGirl2 );
alert( strGirl3 );
}
// Call test funciton.
Test();
// Alert three ORIGINAL girls.
alert( strGirl1 );
alert( strGirl2 );
alert( strGirl3 );
-----
Notice that in the first THIS reference, I am building the name of the variable as it exists within the window parent object. However, when I call the Test() method, and try to change the variable name using THIS, it DOES NOT set the function-scoped variables. It changes the original, window-scoped variables.
My suggestion is that anytime you want to create dynamic variable name, do so WITHIN an object:
var objVars = new Object();
objVars[ "Girl1" ] = "Jamie";
objVars[ "Girl2" ] = "Steffie";
objVars[ "Girl3" ] = "Gizelle";
objVars[ "Girl" + 2 ] = "Laura";
for (var i = 1 ; i <= 3 ; i++)
alert( objVars[ "Girl" + i ] );
---
This way, you will always be able to use structure object notation when referring to dynamic names.
Hi ben, i'm trying your dynamic variable naming technique and it's not working as expected with my example.
Your example
<!--- Set the dynamic variable naming used quoted evaluation. --->
<cfset "Girl#intGirl#" = "super sexy" />
My example uses a couple of structs, local and myStruct, but that's the only difference..
<cfset "local.myStruct.#temp#" = "some val"
i get the error
"The string "local.myStruct.1" is not a valid ColdFusion variable name",
which seems that coldfusion isn't taking the "" off the desired variable name.
I'd use an array to solve it, except temp isn't going to be sequential numbers and i am not sure how many values are in the list which populates the temp variable as it is returned from a query. any ideas how to work it within structs?
Jono,
The issue here is that your struct keys are numbers. While this isn't a problem when using array notation (ie. objStruct[ 1 ] =...), variable names in ColdFusion cannot start with numbers. When you try to go with the dynamic names, it can only use proper variables names.
If you change the naming convention slightly, to have a letter before it, it will work:
<cfset LOCAL.Struct.a1 = "test" />
<cfset "LOCAL.Struct.a#(1)#" = "another test" />
This should work since the thirst level variable name starts with "a" which is valid, not a number, which is invalid.
I'm trying to set up a list loop that will list the specific contents of a directory according to a market name, as well as the recordcount (from a CFDIRECTORY) for each. I know I dont' HAVE to give each iteration query a different name, but for keeping things straight, I'd like to. I'm already setting the queryname using quotes, as per your suggestion; but how can I display said query name, or reference the recordcount of the queries if the name keeps changing?
Thank you, so much, for your site.
^_^
Got it. Had to play with it a bit, but I got the answer I was looking for:
<cfdirectory directory="#dirName#" action="list" name="#marketname#Files" filter="*#marketname#*.txt" sort="name ASC">
<cfif "#marketname#Files.recordCount" gt 0>
<cfoutput>Files found: #"#marketname#Files.recordCount"#<br><cfloop query="#marketname#Files">#name#<br></cfloop></cfoutput>
<cfelse>
<cfoutput>No files found for #marketname#.</cfoutput>
</cfif>
^_^
Scratch that. Close, but no cigar. Still working on it.
^_^
Got it. Your examples of how you used to do it gave me an idea.
#VARIABLES[marketplace & "Files"].recordCount#
Thanks,
^_^
@WolfShade,
Ha ha, no problem - glad you got it working :)
I'm trying to create name of variable1 from string and another variable2 - for example APPLICATION.language.
<cfset variable1 = 'name_' & APPLICATION.language>
and then use is as a table in query
<cfquery name ="q1">SELECT * FROM table</query>
<cfoutput query="q1">#variable1#</output>
BUT problem is that output is not value from database but value of variable1, for example 'name_en'.
Any suggestions?
Thank you.
@Vlad,
I think you are trying to reference the column from within the query. If so, try this:
q1[ variable1 ]
Thanks for reply, Ben. Problem was that I had to use evaluate.
This is correct: #evaluate('name_' & variable)#
@Vlado,
Did you try the query[] notation? I find that using evaluate() usually means that something else isn't working properly (not all the time, but I use it with caution).
Looks like query notation doesnt work for me.
Here is my example tha works:
<cfoutput query="q1">#evaluate('string_' & APPLICATION.language)# </cfoutput>
This doesnt work:
<cfoutput>#q1['string_' & APPLICATION.language]# </cfoutput>
Error:Complex object types cannot be converted to simple values.
I just want to make clear that " 'string_' & APPLICATION.language " create name of column in my table "string_en".
@Vlado:
when using array notation on query columns, one must specify a row number as well:
<cfoutput>#q1[variable1][1]#</cfoutput>
Azadi
@Azadi,
Excellent catch! Thanks for pointing that out.
@Azadi,
thank you , I've tried your example:
<cfoutput query ="q1">
#q1['string_' & APPLICATION.language][2]#
</cfoutput>
and result is the same value.
It looks like it does not loop (i dont want to use cfloop)
I have created a variable "variable_1" that contains the name of a dynamic variable. I want to output the value of variable_1 as a variable...
ex.<cfset variable_1 = "group_#icounter#">
<cfoutput>#variable_1#</cfoutput>
this obviously outputs the value as text but i want to output the name to extract data from an existing variable with the same variable name. I hope this makes sence?
And the answer is #evaluate(variable_1)#
@Ricelle,
I try to avoid using evaluate() whenever possible. In your case, you simply need to access the variables scope explicitly:
#variables[ variable_1 ]#
You rock! Works like a charm. Thanks for the post.
Hi Ben,
How about this one. I've got an array of structs I want to populate from a columnlist.
<cfset arrayAppend(args.tempPeople,structNew())>
<cfloop list="#columnlist#" delimiters="," index="field">
<cfset "args.tempPeople[#arrayLen(args.tempPeople)#].#field#" = evaluate("args.qryGetMembers.#field#")>
</cfloop>
It doesn't seem to like this, any ideas?
@Jim,
Queries can be referenced using array notation:
query[ "columnName" ][ rowIndex ]
This allows you to create dynamic values for both the column name and the row index. Given that, you can probably do something like:
<cfset args.tempPeople[ arrayLen( args.tempPeople ) ][ field ] = args.qryGetMembers[ field ][ args.qryGetMembers.currentRow ] />
Does that help?
Thanks Ben, that's sorted my problem out.
Many thanks
Jim
@Jim,
Awesome.



