ColdFusion 8 Most efficient use of variable - coldfusion

I am parsing a file and need to do something based on the file's content. Which is most efficient, would use less resources or is best practice.
Accessing the file item within the if statement directly
Assigning that items value to a variable.
Here is an example of each:
(1)
<cfset file = XmlParse(file.filecontent)>
<cfif file.item1.xmltext neq "" & file.item2.xmltext neq "">
or
(2)
<cfset file = XmlParse(file.filecontent)>
<cfset item1 = file.item1.xmltext>
<cfif item1 neq "">
Keeping in mind that the same variable maybe accessed a few times throughout the program to test conditions.

Related

Parse the contents of a Coldfusion variable into separate variables

OK, so I've been banging my head against this one for a while and getting nowhere. I've been attempting to take the contents of a variable and parse the contained string into parts that would then be ingested into 5 separate variables. Seems simple enough right? Well, it has not proven to be simple at all, at least for me.
So I have a variable (PageContent) that contains the trimmed content from a CFHTTP request.
The PageContent variable now contains:
<tdnowrapalign=right>07/18/2020 13:00</td>
<tdalign=right>1002.12</td>
<tdalign=right>2,874,887</td>
<tdalign=right>12,766</td>
<tdalign=right>13,038</td>
It seems like there should be an easy way to write a loop that would loop over the tags in the "PageContent" variable assigning the content of each tag to a different variable. But every way I try to parse the data in the variable I either get an error (Complex object types cannot be converted to simple values.) or I end up with the content that I originally had in the "PageContent" variable repeated within the loop.
For instance, if I had a loop that would run through 5 iterations and could grab the contents of the tags assigning each to a variable then the desired result would be:
DateTime = "07/18/2020 13:00"
Elevation = "1002.12"
Storage = "2,874,887"
Outflow = "12,766"
Inflow = "13,038"
After trying every example I could find here and elsewhere online I'm now on something like my 100th attempt. Now I'm trying to use regular expressions to grab the contents of the tags and assign them to variables but no luck there. What I ended up with was the entire contents of the PageContent variable being stuffed into each one of the variables. The result was not really unexpected since I don't know of a way to differentiate between the 3 identical "tdalign" tags, but still it seems like at least the first variable would have worked since the tag was different "tdnowrapalign".
<cfset i=5/>
<cfloop index = "LoopCount" from = "1" to = #i#>
<cfif i EQ 1>
<cfset dataDateTime = Replace(PageContent, "<[tdnowrapalign][^>]*>(.+?)</[td]>","","ALL")>
<cfelseif i EQ 2>
<cfset elevation = Replace(PageContent, "<[tdalign][^>]*>(.+?)</[td]>","","ALL")>
<cfelseif i EQ 3>
<cfset storage = Replace(PageContent, "<[tdalign][^>]*>(.+?)</[td]>","","ALL")>
<cfelseif i EQ 4>
<cfset outflow = Replace(PageContent, "<[tdalign][^>]*>(.+?)</[td]>","","ALL")>
<cfelseif i EQ 5>
<cfset inflow = Replace(PageContent, "<[tdalign][^>]*>(.+?)</[td]>","","ALL")>
</cfif>
<cfoutput>
<cfif isdefined("dataDateTime")>
dataDateTime = #dataDateTime#<br>
</cfif>
<cfif isdefined("elevation")>
elevation = #elevation#<br>
</cfif>
<cfif isdefined("storage")>
storage = #storage#<br>
</cfif>
<cfif isdefined("outflow")>
outflow = #outflow#<br>
</cfif>
<cfif isdefined("inflow")>
inflow = #inflow#<br>
</cfif>
</cfoutput>
<cfset i = i - 1>
</cfloop>
Does anyone know if there is a way to get to the desired outcome I described where I end up with 5 variables containing the contents of the tags contained within the "PageContent" variable?
One way of doing it would be like this
<cfset PageContent = '<tdnowrapalign=right>07/18/2020 13:00</td>
<tdalign=right>1002.12</td>
<tdalign=right>2,874,887</td>
<tdalign=right>12,766</td>
<tdalign=right>13,038</td>' />
<cfset data = ListToArray(PageContent, '</td>', false, true) />
<cfset DateTime = ListLast(data[1], '>') />
<cfset Elevation = ListLast(data[2], '>') />
<cfset Storage = ListLast(data[3], '>') />
<cfset Outflow = ListLast(data[4], '>') />
<cfset Inflow = ListLast(data[5], '>') />
Demo: https://trycf.com/gist/b4f3b630bd1cbdc505d07a7d79b68ef5/acf?theme=monokai

Dynamic variable containing numbers

I've tried everything I've found that might be applicable to this, without success to date.
I have variables that look like
x000Foo
I'm trying to create one of these dynamically in form scope from query results and have tried the following, and a few others, without success:
<cfloop query="qFormFields">
<cfset "form.x000#fieldname#" = 0>
You have attempted to dereference a scalar variable of type class coldfusion.sql.QueryColumn as a structure with members
<cfset "form.x[000]#fieldname#" = 0>
The value x000AA_report cannot be converted to a number.
<cfset form["x000#fieldname#"] = 0>
The value x000AA_report cannot be converted to a number.
</cfloop
I know it's related to the zeros, but I'm not sure how to get around it without resorting to renaming these variables throughout the application.
I'm on ColdFusion2016
I'm not sure if this is what you're trying to do: but here's how you can do dynamic variables:
<cfset fieldname = "foo">
<cfset form["x000" & fieldname] = 0>
<cfdump var="#form#">
<!--- variable form.x000Foo = 0 --->
Runnable example on TryCF.com
you can try evaluate function read more
<cfloop query="qFormFields">
<cfset fieldvalue = Evaluate("form.x000#fieldname#")>
<cfdump var="#fieldvalue#">
</cfloop>
let me know if it is working or not.

ColdFusion Multi Check isDefined(session) and is not blank

I am trying to say if this isDefined and is not blank show this..
<cfif (isDefined("session.checkout.info.Certificate_2")) is not "">
I also tried:
<cfif (isDefined("session.checkout.info.Certificate_2")) neq "">
Will someone please tell me why this still shows when the string is empty?
Consider using structKeyExists (it has lower overhead than isDefined) but here you go:
<cfif
isDefined("session.checkout.info.Certificate_2")
AND session.checkout.info.Certificate_2 NEQ "">
If it exists it will then check to see if it's empty. If it doesn't exist, it won't check the value.

ColdFusion isDefined

I am trying to check to see if data exist in my form If data does not exist I want to assign it to O. How can I do this.
<cfif not isDefined("FORM.Age")>
cfset FORM.Age = "0"
<cfif>
Generally the best practice is considered to be to avoid isDefined. This is because isDefined will search all scopes until it finds a matching variable. So it's more efficient to use structKeyExists, eg:
<cfif NOT structKeyExists(form, "age")>
<cfset form.age = 0>
</cfif>
Also, another way to achieve this is to use cfparam, and specify 0 as the default:
<cfparam name="form.age" default="0">
You're almost there:
<cfif not isDefined("FORM.Age")>
<cfset Form.Age = 0>
</cfif>
Technically what you have is fine once you enclose the cfset in tags < and >. Assuming that omission is just a typo, could it be you are trying to use it with a text field?
Text fields always exist on submission. The value may be an empty string, but the field itself still exists, so IsDefined will always return true. If that is the case, you need to examine the field length or value instead. Then do something if it is empty according to your criteria. For example:
<!--- value is an empty string --->
<cfif NOT len(FORM.age)>
do something
</cfif>
... OR
<!--- value is an empty string or white space only --->
<cfif NOT len(trim(FORM.age))>
do something
</cfif>
... OR
<!--- convert non-numeric values to zero (0) --->
<cfset FORM.Age = val(FORM.Age)>
There are actually two things you want to to ensure. First, make sure this page was arrived at by submitting the proper form. Next, ensure you have a numeric value for the form.age variable. Here is an example of how you might want to code this:
<cfif StructKeyExists(form, "age") and cgi.http_referrer is what it should be>
<cfif IsNumeric(form.age) and form.age gt 0>
<cfset AgeSubmitted = int(form.age)>
<cfelse>
<cfset AgeSubmitted = 0>
</cfif>
...more code to process form
<cfelse>
...code for when page was not arrived at properly
</cfif>

Having some trouble understanding loops

I created this for some reason neither one of the queries are being updated
<cfloop index="i" from="1" to="#ArrayLen(location)#">
<cfif location[i] NEQ "" AND #locationID# EQ "" >
<cfquery Name="UpdateAddActivity" DATASOURCE="#DS#">
INSERT INTO tblProjectLocations
(
projectID,
locationID
)
VALUES
(
#ProjectName#,
#location[i]#
)
</cfquery>
</cfif>
<cfif location[i] EQ "" AND #locationID# NEQ "" >
<cfquery Name="UpdateAddActivity" DATASOURCE="#DS#">
DELETE FROM tblProjectLocations
WHERE locationID = #locationID# AND projectID = #ProjectName#
</cfquery>
</cfif>
</cfloop>
Am I looping correctly? It doesn't seem like to me that the accumulator is ever going to be updated but loops are done this way every place that I've looked.
Your cfloop tag is fine - you only need index/from/to attributes for a basic loop.
The index variable is incremented (and the loop re-processed) at the position of the closing tag. Or to put it another way, the body code is executed once for each index value between from and to (inclusive).
For information, you can change the default increment (of 1) by specifying the step attribute (though that obviously doesn't make sense for an array loop).
When your code isn't performing as expected, you can debug it with the dump tag:
<cfloop ... >
...
<cfdump var=#locationID# abort />
...
</cfloop>
The abort attribute will stop processing - the loop will not iterate and the current page content will be returned (it's shorthand for specifying cfabort tag separately.
You can use multiple dumps, and the label attribute to help identify which is which, but obviously if using abort attribute make sure only the last one has it.
As has been mentioned locationID isn't defined in the snippet you've provided, so may be the issue.
Sometimes spaces can cause issues - you may want to use the trim function to ensure you're dealing with empty strings (though blindly wrapping trim functions everywhere is ugly - always try if possible avoid introducing spaces).
Shortcut Array Looping
The from/to loop you've got there is only one type of cfloop - there are others.
Specifically, when you don't need the numeric index, there is a shorthand array loop:
<cfloop index="CurLocation" array=#Location# >
...
</cfloop>
Which is equivalent to:
<cfloop index="i" from=1 to=#ArrayLen(Location)# >
<cfset CurLocation = Location[i] />
...
</cfloop>
But without the unused i variable. (If you need the i variable, stick to from/to.)
Note that inside a function you should almost always write index="local.i" and index="local.CurLocation" to ensure the variables are appropriately scoped. This isn't unique to loops - it applies to any tags that create variables. You can also do <cfset var i = 0 /> prior to the loop to do the same thing.
Unrelated Issues
There are a couple of other issues with your code.
Most importantly, the code you're showing is potentially at risk of SQL injection. You should almost never write SQL with bare hashes in, and instead parameterise your queries - using cfqueryparam tag - to solve this. (In the situations where you can't use parameters (e.g. within ORDER BY) make sure you have appropriately sanitized any dynamic text.
Less important -- it doesn't change how the code works, but does betray a lack of experience and understanding -- are the superfluous hashes around locationID. A simplified explanation is that you generally only need #s inside strings (i.e. where the contents would otherwise be treated as text, rather than being a variable's value.)
When in doubt, look at your data.
<cfoutput>
<cfloop index="i" from="1" to="#ArrayLen(location)#">
i is #i# <br>
<cfif location[i] NEQ "" AND locationID EQ "" >
true location is #location[i]# <br>
<cfelse>
false location [i] is is #location[i]# and
locationid is #locationID# <br>
</cfif>
<cfif location[i] EQ "" AND locationID NEQ "" >
same as above
</cfif>
</cfloop>
</cfoutput>
Then you'll know why you are not getting the results you expect.
As long as there are items in your location array, the loop will run and the CFLoop tag will take care of incrementing i.
What I'd guess is happening is that you are checking two conditions within the loop and if neither match, no code will run. You're handling these:
location[i] NEQ "" AND #locationID# EQ ""
location[i] EQ "" AND #locationID# NEQ ""
but not these:
location[i] EQ "" AND #locationID# EQ ""
location[i] NEQ "" AND #locationID# NEQ ""
Could that be it?