Dynamic ColdFusion Variables Via Quoted Naming

Posted July 20, 2006 at 8:18 AM

Tags: ColdFusion

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  |  Permalink  |  Other Searches  |  Print Page



Learning ColdFusion 9 - ColdFusion 9 tutorials, samples, examples, demos

Reader Comments

Sep 5, 2006 at 9:03 AM // reply »
1 Comments

I am looking for a way to do exactly this in JavaScript. Any ideas?


Sep 5, 2006 at 9:47 AM // reply »
6,516 Comments

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.


Sep 19, 2006 at 10:06 PM // reply »
1 Comments

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?


Sep 20, 2006 at 10:56 AM // reply »
6,516 Comments

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.


Jul 2, 2009 at 3:51 PM // reply »
4 Comments

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.

^_^


Jul 2, 2009 at 4:03 PM // reply »
4 Comments

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>

^_^


Jul 2, 2009 at 4:05 PM // reply »
4 Comments

Scratch that. Close, but no cigar. Still working on it.

^_^


Jul 2, 2009 at 4:15 PM // reply »
4 Comments

Got it. Your examples of how you used to do it gave me an idea.

#VARIABLES[marketplace & "Files"].recordCount#

Thanks,

^_^


Jul 3, 2009 at 8:49 AM // reply »
6,516 Comments

@WolfShade,

Ha ha, no problem - glad you got it working :)


Jul 23, 2009 at 9:41 PM // reply »
4 Comments

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.


Jul 24, 2009 at 7:52 AM // reply »
6,516 Comments

@Vlad,

I think you are trying to reference the column from within the query. If so, try this:

q1[ variable1 ]


Jul 24, 2009 at 10:10 AM // reply »
4 Comments

Thanks for reply, Ben. Problem was that I had to use evaluate.
This is correct: #evaluate('name_' & variable)#


Jul 24, 2009 at 12:21 PM // reply »
6,516 Comments

@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).


Jul 24, 2009 at 11:24 PM // reply »
4 Comments

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".


Jul 25, 2009 at 7:25 PM // reply »
10 Comments

@Vlado:
when using array notation on query columns, one must specify a row number as well:

<cfoutput>#q1[variable1][1]#</cfoutput>

Azadi


Jul 27, 2009 at 8:41 AM // reply »
6,516 Comments

@Azadi,

Excellent catch! Thanks for pointing that out.


Jul 27, 2009 at 11:42 AM // reply »
4 Comments

@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)


Sep 29, 2009 at 2:43 AM // reply »
2 Comments

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?


Sep 29, 2009 at 2:56 AM // reply »
2 Comments

And the answer is #evaluate(variable_1)#


Sep 29, 2009 at 8:08 AM // reply »
6,516 Comments

@Ricelle,

I try to avoid using evaluate() whenever possible. In your case, you simply need to access the variables scope explicitly:

#variables[ variable_1 ]#


Post Comment  |  Ask Ben

Recent Blog Comments
Nov 22, 2009 at 7:37 AM
Using A Name Suffix In ColdFusion's CFMail Tag
asd ... read »
Nov 22, 2009 at 4:30 AM
jQuery Live() Method And Event Bubbling
dasegtezr ... read »
Nov 22, 2009 at 4:03 AM
jQuery Live() Method And Event Bubbling
C_fieri ... read »
Nov 22, 2009 at 1:56 AM
Learning ColdFusion 9: Using CFQuery In CFScript Can Enable SQL Injection Attacks
Why adobe would give you script equivalent of cfquery is beyond me. I love cfquery tag because it helps me wriite clean sql, and get away from the horrible jdbc queries If I wanted to write javali ... read »
Nov 22, 2009 at 1:45 AM
Streaming Text Using ColdFusion's CFContent Tag And The Variable Attribute
The reason you would want to do this is to stream. Ack json/xml files to ria clients I used thus technique before because putting json in response stream causes debugging info to come thru As well a ... read »
Nov 21, 2009 at 6:47 PM
Hal Helms - Real World Object Oriented Development, Sarasota - Day Five
@charlie griefer, Thank you.. ... read »
Nov 21, 2009 at 5:15 PM
Using ColdFusion Structures To Remove Duplicate List Values
@Jose Galdamez, Oh heh yeah I didn't paste the whole code. I should have defined the vars -- my bad. It's fixed thou. Thanks. ... read »
Nov 21, 2009 at 4:49 PM
Styling The ColdFusion 8 WriteToBrowser CFImage Output
Great work yet again Ben! Whilst I didn't use this whole code, I copied some of your regex code for a similar problem with the lack of an alt attribute and unescaped ampersands in CFIMAGE for Railo 3 ... read »