Archive for the ‘Coldfusion’ Category

Coldfusion Code Efficiency Tips

Thursday, March 18th, 2010

This is as summary of what I’ve learned about code efficiency in the past
couple of weeks. A lot of the things I didn’t even think about are actually
wrong, or at least not as efficient as they could be. The general idea is to
cut back on evaluation as much as possible.

Using structKeyExists() instead of isDefined()

Think about it, ALL coldfusion variables are in structures, right? So
instead of isDefined(’myvar’) where coldfusion doesn’t know what struct to start
in and therefore has to look through every scope to find the instance of myvar
and see if it exists, you are now telling coldfusion exactly where to look using
structKeyExists(’variables’, ‘myvar’). It’s the difference between someone
saying “turn to page 123 paragraph 2 on Insects” and “find the part about Insects”. Well, you can go to the index in the book and look at all of the places Insects are mentioned, or you can just go to the page because the information was given to you… much better!

Looping

Everyone has done it, the classic loop through a list. Here’s how it would
look:

<cfloop from="1" to="#listlen(mylist)#" index="i">
#i#
</cfloop>

Ok, that’s decent code, and certainly what you will find out there as the
“standard” way of doing things, but this can be more efficient:

<cfset loopThrough=listlen(mylist)>
<cfloop from="1" to="#loopThrough#" index="i">
#i#
</cfloop>

Why? Instead of having to not only loop through your list x number of times,
the first example would also be evaluating #listlen(mylist)# x times as well…
twice the effort! It’s much less taxing on the system to define variables than
to re-evaluate over and over… even if it is less characters on the page.

If it’s boolean, don’t bother with the “eq 1″ or “neq NO” etc.

If you are going to have a boolean returned by a variable, don’t bother
setting what it’s equal to, you’re just wasting space, plus your code looks
cleaner. Examples:

<cfset isEfficient = 1>
<cfif isEfficient>it's efficient!</cfif>
<cfif isEfficient = '1'>It's NOT as efficient.</cfif>

The variable above, “isEfficient” could also be set to any of these boolean
combinations and it would still work:

  • yes/no
  • true/false
  • 1 (OR ANY numeric value that is NOT 0… yes, that means ‘-.000001′ &
    59990289 will both evaluate True) / 0

Eliminate “Else” from If statements where possible.

If you’re like me, this one seemed ridiculous, right? I know I thought I
only used “else” when necessary, but I was SO wrong. I have to admit though,
this is a method that is really used more on the presentation side than the
logic side, even though you can apply it to both. Let’s see an example.

This is a pretty classic example. Let’s say we have a bunch of table rows we
want to have with colors that fluxuate by row. First, we’ll look at the if/else
way:

<cfloop from="1" to="5" index="i">
 <cfif NOT mod(i)>
  <td style="color: red">&nbsp;</td>
 <cfelse>
  <td style="color: blue">&nbsp;</td>
 </cfif>
</cfloop>

Let’s see what we can do to Improve.

<!--add to css style-->
.line0 {color: red}
.line1 {color: blue}
<cfloop from="1" to="5" index="i">
 <td class="line#mod(i)#">&nbsp;</td>
</cfloop>

Much Better! But there is more to it than just this example. Let’s look at
a different example:

<cfset isWidgets = 1>
<cfif isWidgets>
 <p>There are widgets!</p>
<cfelse>
 <p>There aren't any widgets...</p>
</cfif>

Ok, so this might not be the most efficient thing to do in every situation,
but as this is an example to build on, here’s how we could eliminate the
“else”:

<cfset isWidgets = 1>
<cfset widgetText = "There aren't any Widgets...">
<cfif isWidgets>
 <cfset widgetText = "There are widgets!">
</cfif>
<cfoutput><p>#widgetText#</p></cfoutput>

It’s important to note that doing this:

<cfset isWidgets = 1>
<cfset widgetText = "">
<cfif isWidgets>
 <cfset widgetText = "There are widgets!">
<cfelse>
 <cfset widgetText = "There aren't any Widgets...">
</cfif>
<cfoutput><p>#widgetText#</p></cfoutput>

Is even less efficient than the first example, because you not only still
have an else statement, but more variables and more characters floating about.
Therefore, we could also glean that starting off by defining a variable with one
of the options for its value is another way to reduce code and increase
efficiency… of course, that’s not possible in many situations, but where it is, it’s a good idea.

Use cfscript

I always shied away from this tag in the past. I was a self taught cf’er and
while I certainly love the simplicity of the tag based cf language, cfscript
isn’t as scary as I thought. You pretty much just strip the “cf” off of the
tags and add some “;”. Sure, there’s a little more to it, but really, you can
figure it out!

Coldfusion Instance Variables

Tuesday, March 16th, 2010

This is a term I have heard thrown around a lot by developers, and while I knew
what they were, I never knew I knew it until recently. So for all of those who
are curious, this is for you.

So, Let’s say we have a very simple cfc:

<cfcomponent displayname="MyCFC">
 <cffunction name="getList" access="public" returntype="struct" output="false">
  <cfset var returnData = "">
  <cfset i = 0>
  <cfloop from="1" to="5">
   <cfset returnData = returnData & ',' & i>
   <cfset i = i + 1>
  </cfloop>
  <cfreturn returnData/>
 </cffunction>
 
 <cffunction name="getList2" access="public" returntype="struct" output="false">
  <cfset var returnData = "">
  <!---notice this function has no i = 0 set--->
  <cfloop from="1" to="5">
   <cfset returnData = returnData & ',' & i>
   <cfset i = i + 1>
  </cfloop>
  <cfreturn returnData/>
 </cffunction>
</cfcomponent>

Ok, so then let’s say we call getList, and then getList2. Here’s what we’d see:

getList= ,0,1,2,3,4
getList2= ,5,6,7,8,9

So, what happened? In our getList function, we declared i = 0. However, we did
NOT declare it as a “var” for the function, and that means that “i” is available
in ALL of your functions, instead of just that one specific function. The above
is set up to not really end up being a problem, but what you will eventually run
into is you will have two functions that may get called at once, and if they are
both manipulating the “i” variable, things will get weird. For example, in the
above example, if both functions somehow manage to get called at the same time,
you may end up with an output like this:

getList = ,0,2,3,7,8
getList2 = ,1,4,5,6,9

Where this can really come back to bite you is if you have several queries you
have not “var” scoped that are all named the same thing. Perhaps you have
several users that are pulling up user-specific data via these separate queries
in separate functions in your cfc, but you forgot to var scope your queries.
Bam… your users start seeing each other’s data occasionally. Problem?
definitely. Lesson: make sure to var scope any variables that are NOT cfc-wide.

So, why did I tell you all that when all you really wanted to know about was
instance variables? Because “i” is an instance variable. It’s just a variable
(and yes, they belong to the “variables” scope) that is available to all of your functions in a component. A lot of times, you
will see these variables thrown into the variables scope just to make keeping
them separate easier. You’ll also commonly see an “init()” function whose job it
is to set all of those instance variables the first time a component is called
just to be sure the variables are available when needed.

<cfcomponent displayname="myCFC">
 <cffunction name="init" access="public" returntype="struct" output="false" hint="this is the init() function for this component">
  <cfset variables.instance = structNew()>
  <cfset instance.myName = "Tess McTesterson">
  <cfset instance.dsn =  "myDSN">
  <cfreturn this/>
 </cffunction>
 
 <cffunction name="getName" access="public" returntype="struct" output="false">
  <cfset var returnData = "">
  <cfset returnData = variables.instance.myName>
  <cfreturn returnData/>
 </cffunction>
</cfcomponent>

So using the above example, this:

<cfset theComponent = createObject("Component","myCFC").init()>
<cfoutput>#theComponent.getName()#</cfoutput>

Would yield:

Tess McTesterson

So, instance variables don’t have their own scope, like “variables” or “form”
it’s just a way to refer to variables that are available in a cfc to all
functions.

What are Session and Application Variables in Coldfusion?

Monday, February 15th, 2010

Ok, just to start, this is not a post for the seasoned coldfusion developer, this is just a “get an idea of what the heck is going on” sort of post. I was attempting to explain a simple coldfusion login and some different options to a friend, and they were simply not understanding the concept because they didn’t know about application and session variables, so I thought i’d tutorialize this for the others out there who are just confused. Sometimes it’s the simple stuff that’s the hardest to start!
First, you should be at least vaguely familiar with Structures. ok? ok!

There are a few concepts to understand when delving into the world of application and session variables, and i will do my best to avoid using techno talk so you can understand it without having to try too hard. The first, is what an application.cfm (or application.cfc) file is/does.

What an Application.cfm (or application.cfc) file is/does

An application.cfm file is a hunk of code that is executed FIRST before any page you create runs. You MUST name it “application.cfm”. It MUST be at the root of your site (well, not always, but for the basics, yes… must.)
Here is what your 1-page website should look like utilizing an application.cfm:

SITEROOT.com
–index.cfm
–application.cfm

Let’s have a look-see here and show you what this will do.

Here’s my ridiculous application.cfm file:

I'm an application.

And the index:

I'm a sweet index page.

Which will output this:

I'm an application.I'm a sweet index page.

So, we understand. Applications run first, ALWAYS. I’m sure this gets your head turning on the nice things you can now do, but this, my friend, is only the tip of the glorious application file iceberg. There are many, many things you can and should use the application file for, but I don’t want to overwhelm you, so I will just get you excited about application variables.

All right. There are some variables that coldfusion makes available to you that you can use on any page, anywhere, always. These are APPLICATION variables. any variable that you set in the application structure is available anywhere in your website, and is the SAME FOR ALL CLIENTS.

Need to have your datasource name saved? set it!

<cfset application.dsn='mydsn'>

Now you can just call your datasource name variable instead of hard coding it in. Why? you ask? because you really, really don’t want people to be able to see your DSN when an error page appears. yeah, not good. they’ll just see the variable name, though if you use the code above!

Mmk, so application variables are for any computer accessing your site, anywhere on your site.

So What is a Session Variable, then?

Unlike Application variables, which (again), once set, can be used by ANY computer, ANY where on your site, Session variables can only be used by ONE computer ANY where on your site. Here is a great example of where session variables would be perfect:

<cfset session.userid=1287>

What does the code above do? it sets up a userid that can be used anywhere on the site, but only for the one particular computer accessing your site. This is one way that you could create a secured back end area for different users without having to pass a url or form variable to every page. Maybe you would like to display a person’s name on some pages of your site, now you can! just set it on one page, and then call it when you need it from any other page. as long as the user is still on your site, their name will appear!

What is a coldfusion structure?

Monday, February 15th, 2010

Well, someone told me they heard the word “structure” get thrown around a lot in coldfusion, but they weren’t really clear on what it was. I thought i’d write a VERY basic overview of structures and coldfusion for those who don’t have the luxury of better-informed-colleagues to ask.
Ok, so you know how you can read variables in coldfusion, right? Well, just to be thorough, let’s review by getting the “oid” from the url:

url: website.com?oid=124

<cfoutput>#url.oid#</cfoutput>

And you get:

124

Easy peasy, right? now for those of you that don’t know, “url.oid” is, like many coldfusion variables, a STRUCTURE. Here are some other examples of structures just so we are clear:

#url.status#
#form.runadd#
#cart.items.sku#

So, in it’s most dumbed down form, it’s just a variable name with some dots thrown in the middle to make them easier to sort, like looking through a list of lists.

Did you know there are some structures available for you to use on EVERY page? YES! EVERY page! And they are super-helpful. Don’t believe me? try running this on any coldfusion page:

<cfdump var="#application#">
<cfdump var="#session#">
<cfdump var="#cgi#">

So, see all that craziness that gets dumped out? those are structures! how do you call one of the things you see… like this:

<cfoutput>#cgi.http_server#</cfoutput>

and there’s your http server’s name. excellent! Hopefully this will arm you with the ability to call just about anything you can dump.

AJAX/Javascript/Coldfusion Dependent Dropdowns with Optional Text Box

Friday, December 18th, 2009

Here’s a common problem. You have a form where you want one select box in a form to be dependent on the other. Coldfusion makes this ridiculously easy with its built in AJAX functionality. Let’s take a gander:

For this example, I set up a cfc called “ajax” (clever, eh?). Here is the function inside it…

 
<cffunction name="getstates" access="remote" returntype="array" hint="lookup states for dropdown">
	<cfargument name="country" type="string" required="true" default="">
 
		<!--- Define variables --->
		<cfset var data="">
		<cfset var i=0>
		<cfset var result=ArrayNew(2)>
 
		<!--- Do search --->
		<cfquery datasource="#variables.dsn#" name="data">
		SELECT state,postal_code
		from tblstates
		where country=<cfqueryparam value="#ucase(arguments.country)#" cfsqltype="cf_sql_varchar">
		order by state
		</cfquery>
 
		<!--- Build result array --->
		<!--- Convert results to array --->
        <cfloop index="i" from="1" to="#data.RecordCount#">
            <cfset result[i][1]=data.postal_code[i]>
            <cfset result[i][2]=data.state[i]>
        </cfloop>
 
		<!--- And return it --->
		<cfreturn result>
	</cffunction>

Mmk, Now let’s look at the actual code on my form page:

<!---here's a query for filling my select box...--->
<cfquery name="rscountry" datasource="#application.db#">
SELECT *
FROM tblcountries
ORDER BY country ASC
</cfquery>
 
<!---here's my form--->
<cfform method="post" name="form1" action="join.cfm?dealeruname=#this_dealer_username#">
     <cfselect name="country" id="country" required="yes" message="Please select your country of residence." query="rscountry" value="country" display="country" selected="United States"></cfselect>
 
     <cfselect name="stateprov" bindonload="true" bind="cfc:ajax.getstates({country})" /> 
</cfform>

That’s it, folks. easy.

But what about when I don’t have a State listing for say… Uganda. Well, we have to have some way of getting the state/province if we don’t have a populated dropdown. Now there’s more to do. There are probably more elegant solutions out there, but this is what I did, and it seems to work pretty well.

Now we’re going to need to use some javascript and a bit more ajax. Let’s do it!

First, let’s get our form prepped:

 
<!---here's my sexier form--->
<cfform method="post" name="form1" action="join.cfm?dealeruname=#this_dealer_username#">
     <!---Notice, I've added an onchange event to this field.--->
     <cfselect name="country" id="country" required="yes" message="Please select your country of residence." query="rscountry" value="country" display="country" selected="United States" 
onChange="showwhich()"></cfselect>
 
   <!---wrap each field in a uniquely identified div--->
    <div id="dd_state">
	<cfselect name="stateprov" bindonload="true" bind="cfc:ajax.getstates({country})" /> 
   </div>
   <!---add a new text input, and hide it with the div--->
   <div id="type_state" style="display:none">
	<cfinput name="stateprovt" type="text" />   
   </div>
</cfform>

OK, we have our text field. It’s hidden. We’ve got all the other stuff in place, we just need to write the stuff that makes it work!

First, we need to make a new cffunction in our ajax cfc. The function will return a boolean value for whether or not the country has states/provinces within it. You could probably set this up to work with your first function, but I went with a smaller query to reduce some load.

<cffunction name="arestates" access="remote" returntype="boolean" hint="are there states?">
	<cfargument name="country" type="string" required="true" default="UNITED STATES">
 
		<!--- Define variable --->
		<cfset var data="">
 
		<!--- Do search --->
		<cfquery datasource="#variables.dsn#" name="data">
		SELECT state
		from tblstates
		where country=<cfqueryparam value="#ucase(arguments.country)#" cfsqltype="cf_sql_varchar">
		LIMIT 1
		</cfquery>
 
		<cfif data.recordcount>
			<cfreturn true>
		<cfelse>
			<cfreturn false>
		</cfif>
	</cffunction>

Ok, not too bad. Now, let’s bind our page to the ajax cfc so we can use this function. Stick this baby at the top of everything on the page:

   <cfajaxproxy cfc="ajax" jsclassname="respond">

Now we need to write the javascript to make the magic happen.

  function showwhich(){
	  var r= new respond();
	  sforc=document.form1.country.value;
	  toshow= r.arestates(sforc);
	  if (toshow == true) 
	  	{
	  	//unhide dropdown, hide text box.
		document.getElementById("dd_state").style.display='inline',
		document.getElementById("type_state").style.display='none',
		document.form1.stateprovt.value=""
		}
	  else {
		//hide dropdown, unhide text box.
		document.getElementById("type_state").style.display='inline',
		document.getElementById("dd_state").style.display='none',
		document.form1.stateprovt.value=""
	  }
 
}

You’ll notice I’ve added a line to clear the value of the text field on each change. This is just idiot-proofing so you don’t have someone come in and enter text, then decide they really did live in the US after all. I have further idiot proofed by adding this code before my form processes:

<cfif isdefined("form.stateprov") and TRIM(form.stateprov) neq ''>
	<cfset use_state=form.stateprov>
<cfelseif isdefined("form.stateprovt") and TRIM(form.stateprovt) neq ''>
	<cfset use_state=form.stateprovt>
<cfelse>
 	<cfset runadd="no">
	<cfset message=message &"<br />The State/Province you entered is invalid.">
</cfif>

Again, I’m sure there are “prettier” ways to accomplish this, but this worked for me!

cffile Disappearing Backslashes

Thursday, November 12th, 2009

I’ve never encountered this one, so I thought I’d share…

I was running this simple rename command on an xml response handler page… very, very simple, right?

<cffile action = "rename" source = "c:\inetpub\mysite\images\tn_0000.png" destination = "c:\inetpub\mysite\images\renamed.png">

But here was the error I was getting:

Attribute validation error for tag CFFILE. The value of the attribute source, which is currently c:inetpubmysiteimages tn_0000.png, is invalid.

Whaaat? where did all my backslashes go?? Well, I don’t know… I guess the bermuda triangle of Coldfusion. Either way, after some trial and error, I found the solution:

<cffile action = "rename" source = "c:/inetpub/mysite/images/tn_0000.png" destination = "c:/inetpub/mysite/images/renamed.png">

just change them all to forward slashes… it worked!

xml post as Bytearray

Saturday, October 24th, 2009

I was working recently on creating a response handler for the flixcloud API.  Fairly standard procedure,

<cfset xmlstr = GetHTTPRequestData().content>
<cfset xmldata = XmlParse(xmlstr)>

Apparently not. It was easy enough to test successfully with my own XML, but running against the actual API yielded this error message every time:

ByteArray objects cannot be converted to strings.

After some investigating, I found the culprit… and, with a simple tostring() around my data, it’s fixed!

<cfset xmlstr = tostring(GetHTTPRequestData().content)>
<cfset xmldata = XmlParse(xmlstr)>

Since we’re talking about working with API’s, another problem I encountered while working with the flixcloud API was syntactically invalid xml names. For examlpe, here in an excerpt from the XML returned:

<job>
<thumbnail-media-file>
   <url>ftp://ftp.MYDOMAIN.com/4F173CA4-3048-7B4D-7B5655ECA9D97CCC.png/tn_</url>
   <total-size>41817</total-size>
   <number_of_thumbnails>1</number_of_thumbnails>
   <cost>9</cost>
 </thumbnail-media-file>
</job>

If you parse this into a coldfusion variable called “xmldata”, you’d think you could get to the “total-size” xml text in this way:

<cfoutput>#xmldata.job.thumbnail-media-file.total-size.xmltext#</cfoutput>

However, you would be wrong. Coldfusion does not like those dashes. Here’s how to call it correctly:

<cfoutput>#xmldata.job["thumbnail-media-file"]["total-size"].xmltext#</cfoutput>

and if you thought you should double quote to escape any database issues, it doesn’t seem to work. just leaving the single quotes worked fine.