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




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 »
7,539 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 »
7,539 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 »
7,539 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 »
7,539 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 »
7,539 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 »
7,539 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 »
7,539 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 ]#


Dec 9, 2009 at 11:13 AM // reply »
1 Comments

You rock! Works like a charm. Thanks for the post.


Feb 4, 2010 at 11:07 AM // reply »
2 Comments

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?


Feb 4, 2010 at 9:14 PM // reply »
7,539 Comments

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


Mar 10, 2010 at 11:01 AM // reply »
2 Comments

Thanks Ben, that's sorted my problem out.

Many thanks

Jim


Mar 10, 2010 at 11:09 AM // reply »
7,539 Comments

@Jim,

Awesome.


Post Comment  |  Ask Ben

Recent Blog Comments
Mar 18, 2010 at 4:04 PM
jQuery's Event Triggering, Order Of Default Behavior, And triggerHandler()
Tks! You saved-me today. it can be chained into one statement: $("#x).attr("checked","checked").triggerHandler('click'); ... read »
Mar 18, 2010 at 1:18 PM
Finally Finished Ayn Rand's Atlas Shrugged Audio Book
@joaopft, Not disputing what you say - but... If I understand you correctly, you are saying that Positivism is based on sense experience (what I experience is what is), but Quantum theory states tha ... read »
Mar 18, 2010 at 11:48 AM
Duplicate() Much Faster Than ColdFusion Query-of-Queries
I am working on a massive xml parsing, qofq app to create 2 seperate xml files. I just don't understand the concept/purpose of duplicate function, are you duplicating the data or the row, into a new ... read »
Mar 18, 2010 at 11:22 AM
Exploring ColdFusion Component Runtime Class Properties And Serialization
@Zarko, Ha ha, you know ColdFusion is my first love ;) ... read »
Mar 18, 2010 at 11:15 AM
Exploring ColdFusion Component Runtime Class Properties And Serialization
Hi Ben, nice to have you back! I already gave up on you, thinking you'll write about jQuery and iPhone for the rest our our lives! :) ... read »
Mar 18, 2010 at 10:36 AM
Ask Ben: Javascript Replace And Multiple Lines / Line Breaks
@Ben Nadel, Hey Ben, thanks for you're response. It works!! However.. if you could please kindly look at http://edeals.zzl.org/divchange2.php where I am trying it out you will see that with the " ... read »
Mar 18, 2010 at 9:56 AM
SQL COUNT( NULLIF( .. ) ) Is Totally Awesome
This works too. I learned this trick a long time ago and it's really powerful for flags. SELECT g.hair , COUNT(*) AS girl_count , sum(did_date) AS did_date_count , sum(abs(did_date - 1)) AS did_ ... read »
Mar 18, 2010 at 9:16 AM
Using A SQL JOIN In A SQL DELETE Statement (Thanks Pinal Dave!)
Forget the last part of that. Wasn't thinking straight and hadn't done it exactly that way myself. It'll work if you're doing an 'In' but if you're doing a 'Not In' as above it'll do each check acr ... read »