How to get rid of Evaluate with Object function call - coldfusion

I call a function through object at runtime. In this specific case, the function name is supplied through a logic from another page at runtime (the function exists in cfc). At present we use Evaluate and that is very slow. Any way I can get rid of this? I know I can use [] with a structure but here I am lost. qryData is the query object which I pass to the function.
<cfset someData = Evaluate("objTicket.#arrayItem[ItemID].FunctionName#(qryData)")>
<!---this is how it would look like--->
<cfset someData = objTicket.getTickets(qryData)>

Does this fix it for you?
<cfset someData = objTicket[arrayItem[ItemID].FunctionName](qryData)>

Related

changing the query mode through ColdFusion to allow IN instead of equals

I am trying to change some content of the query through ColdFusion. Well I cannot try in query itself because I am getting query from an external source
I have the following query
(q.company_na = 'a, b, c, d')
and I am trying to convert it to
(q.company_na in ('a, b, c, d'))
I am using a normal replace but that is not gonna solve the issue. I have seen my try is like this
<cfset data = Replace(data,'q.company_na = ','q.company_na IN ','ALL')>
but I am missing the opening and closing braces around the IN. How can I approach this?
Another benefit of query parmaters
where q.company_na in (
<cfqueryparam cfsqltype="cf_sql_char" value="a,b,c,d" list="yes">
)
Playing a riff off Dan's answer, you can add parameters to the query object.
Find all the equality operators in the query.
For each equality operator found,
Store the right-hand side into a temporary variable.
Replace the equality operator and the right-hand side with IN (?).
Add a parameter to the query object (query.addParam(...), see query object documentation) using the value you stored in the temporary variable.
Make sure to remove white-space from around the list delimiters.
Make sure to set the list property of the parameter to true.
Set the sql property of the query object with the modified SQL.
Could you try something like this?
<cfset str = "(q.company_na = 'a, b, c, d')" />
<cfset str = REReplace(str, "(,)\s*", "'\1'", "all") />
<cfset str = REReplace(str, "= ('[^)]*)", "IN (\1)") />
Output:
(q.company_na IN ('a','b','c','d'))
If you want your output to be
(q.company_na in ('a, b, c, d'))
(which I can't imagine you do, since that is semantically the same as using = in this instance), then simply omit the second line above and do this:
<cfset str = "(q.company_na = 'a, b, c, d')" />
<cfset str = REReplace(str, "= ('[^)]*)", "IN (\1)") />

ColdFusion Syntax

I'm trying to modify existing codes in my ColdFusion application left by previous programmer. I don't understand the meaning of this line of code (the one with question marks):
<cfset Application[#form.username#] = 0> ??????
<cfset Session.loggedin="Yes">
<cfset Session.username="#Trim(Form.username)#">
Maybe I haven't been working with CF long enough to see this syntax so I don't know what this mean.
When setting an application variable I usually use this syntax:
<cfset application.variableName = "some value">
Can someone explain to me what is this ?
Thank you
As well as explicitly stating variable names at "code time" with dot notation, CFML allows one to reference them dynamically at runtime via a string value.
This is done via associative array notation (using square brackets), eg:
myVariableName = "foo";
variables[myVariableName] = "moo"; // equivalent to variables.foo = "moo"

convert string to variable coldfusion

I'm a bit stumped on this one..
I currently have a string.
Please enter your variable.firstname here
What i would like to do is find the variable.firstname in the string and convert it to be used as #variable.firstname#
Im using CF8, and ive looked at using findNoCase() but the variable.firstname portion can appear anywhere. I am also trying to use this in a Coldfusion Custom Tag as its to simply display the firstname of the user that could be dynamically populated.
I cant use any other functionality to change it IE = variable['firstname] because the variable could be the result of a dynamic variable i pass in and the query for the content will reside within the custom tag.
<cfset yourNewString = replace(yourOldString,'variable.firstname',
'##variable.firstname##', 'all')>
Note the double pound signs.
I cant use any other functionality to change it IE =
variable['firstname] because the variable could be the result of a
dynamic variable i pass in and the query for the content will reside
within the custom tag.
I'm not sure I understand exactly what you're saying here but if you're saying that variables.firstname is coming from another variable and the .firstname is the dynamic part you could still use array notation.
<cfset myName = "Travis">
<cfset yourName = "user125264">
<cfset myCustomVariable = "myName">
<cfoutput>Hi, My name is #variables[myCustomVariable]#. </cfoutput>
<cfset myCustomVariable = "yourName">
<cfoutput>Your name is #variables[MyCustomVariable]#.</cfoutput>
Output: Hi, My name is Travis. Your name is user125264.
If that isn't what you meant, I apologize.
If you're trying to replace variable.firstname with #variables.firstname# and then also get the value of that variable, you'll need to do the replace <cfset yourNewString = replace(yourOldString,'variable.firstname',
'##variables.firstname##', 'all')> and then wrap the resulting string in an evaluate() function (and an inner de() to prevent CF from evaluating everything): <cfset evaluatedString = evaluate(de(yourNewstring))>.
If there are more variables besides variable.firstname that need this kind of translation, you'll need to get into regex with reReplace() to catch them all in one statement. My regex is rusty, so you'll need to Google that bit on your own. ;o)

Why is ListAppend non destructive, while ArrayAppend and StructInsert are both destructive?

I just spent almost an hour trying to figure out an issue with having a list that would always return an empty string. I was using ListAppend just like one uses ArrayAppend or StructInsert, but apparently ListAppend works differently. What, if any, is the reasoning behind having ListAppend work differently from everything else?
<cfset ListAppend(list, item)>
list = ''
<cfset ArrayAppend(array, item)>
array[1] = item
<cfset StructInsert(struct, 'key', item)>
struct.key = item
Possibly because a list is just a big String. Unlike arrays and structures, Strings are immutable, meaning they cannot be changed. To "append" a new value, you need to create an entirely new String. Arrays and structures are mutable. So you can modify them "in place".
Lists in ColdFusion are just Strings and strings in ColdFusion (and Java) are immutable. They cannot be changed. So ListAppend() must return the a new string with the value instead of modifying the existing string.
<cfset newList = listAppend(oldList, "New Value") />

Can you var scope multiple variables at once in Coldfusion?

While it is possible and does not throw an error I would like to know if it's an approved practice to var scope multiple variables in one line like this:
<cfset VAR var1 = var2 = var3 = ''>
I would appreciate all ideas and opinions especially if they come with documentation as a supporting argument. I know that it works without throwing an error but I can't find specific documentation saying whether it will scope a variable or if it just declares the value.
Thanks!
FWIW, yes, you can do this in CF9:
<cfset var a = var b = c = d*5>
Here's the documentation which gives that example. In this case I'm assuming variables c and d were already defined earlier in the function.
So you need to repeat the var keyword for each variable, and in your case this would result in:
<cfset VAR var1 = VAR var2 = VAR var3 = ''>
As everyone said you need to scope your variables with var or local. Also as #Ben said, you can't really var scope variables like you have. What I would suggest is use the local scope and do something like the following:
<cfscript>
var val = 'some value'
local = {
var1 = duplicate(val),
var2 = duplicate(val),
var3 = duplicate(val)
};
</cfscript>
That, in my opinion, is the fastest way to achieve what you seem to be doing. I use the duplicate function just so if you use a complex variable as the value of val (struct, array, etc) you don't run into issue with references.
<cfset> does not scope variables.
To properly scope the variables requires the var keyword
<cfset var someVariable = 1>
Otherwise the variables will be created, but assigned to the default scope.
The default scope depends on the context and what version of CF we are talking about.
For CFC methods:
CF9 -> LOCAL scope
CF8 -> VARIABLES scope
Because of the scoping rules in CF9 the var keyword is not really needed.
Variables can be added to the LOCAL scope directly and at any time (<cfset LOCAL.foo = "bar"). There is no need scope them ahead of time.
I suppose I should start by pointing out that your code doesn't var scope the variables, it just sets their values. You need to use the VAR keyword (or LOCAL scope in CF9) to specify that the variables should be VAR scoped.
Furthermore, chaining assignments doesn't work in all versions of CF. My workplace is still on 6.1, and this throws an error.
Finally, if I recall correctly, if you use the assignment statement as above, var1 and var2 are equal to true, as the result of an assignment operation is true if no error occurred. (someone correct me if I'm wrong, since I can't test it at work, since we're on 6.1)
Anyway, to get back to your question, I don't chain assignment or scoping ever. First, I think individual assignments are clearer. second, it doesn't work in all versions. So I would suggest that individual assignments would be preferred.
I've seen people simply create a var struct and define your variables as keys for the struct. This way you don't have to use var all the time. E.g.:
<cfset var local = structNew() />
<cfset local.var1 = "" />
<cfset local.var2 = "" />
This is helpful for those who use ColdFusion Server 8 and below and are stuck with the var scope.