Home / Articles / Learn to Write Script-Based Syntax in ColdFusion 8: It's Easier Than It Sounds

Learn to Write Script-Based Syntax in ColdFusion 8: It's Easier Than It Sounds

Chapter Description

The world's leading ColdFusion experts show you how to use script-based syntax to make writing code just a little easer in ColdFusion 8.

Implementing <cfscript>

To use ColdFusion scripting in your templates, place a <cfscript></cfscript> tag pair in a template, and then write ColdFusion scripting statements in the body of the tag.

You can intersperse <cfscript> blocks with blocks of tag-based CFML throughout a ColdFusion template, but you should strive to combine your ColdFusion scripting into as few <cfscript> blocks as is feasible. ColdFusion Server executes both ColdFusion scripting statements and tag-based CFML in the order they are placed on the page, so if scripting statements create variables or other objects that will be used by tag-based CFML, then you must place that script before those tags.

The only exception to this rule is with user-defined functions, which you can call before they appear in the template. However, it is considered a best practice to define functions above the statements that call them. This is less confusing for you and other developers because the code reads in a natural order.

Creating and Using Variables

To assign a value to a variable in a script, just provide the variable name, the equal sign (=), and then the actual value you want to assign to the new variable. If you want, the value can come from an expression made up of any valid combination of ColdFusion operators and functions.

In Listing 44.2, I’m showing both the scripting and tag-based versions of the same variable assignments so you can compare them. Try commenting and uncommenting each section and perhaps varying the values being assigned.

Listing 44.2. CreatingVariables.cfm—Creating Variables Using ColdFusion Scripting

<!--- Author: Adam Phillip Churvis -- ProductivityEnhancement.com --->
<!--- Creating variables --->

<!--- A simple variable --->
<cfset welcomeMessage = "Welcome to ColdFusion scripting!">

<!--- An array --->
<cfset gameScores = ["93","87","96"]>


<!--- A structure --->
<cfset player = {name="John Doe", age="27", gender="Male"}>

<cfscript>
  // A simple variable
  welcomeMessage = "Welcome to ColdFusion scripting!";

  // An array
  gameScores = ["93","87","96"];
  // A structure
    player = {name="John Doe", age="27", gender="Male"};
</cfscript>

<p><cfoutput>#welcomeMessage#</cfoutput></p>
<p><cfdump var="#gameScores#" label="gameScores"></p>
<p><cfdump var="#player#" label="player"></p>

Basically, to convert a tag-based variable declaration into a script-based declaration, you just use the guts of the <cfset> tag and terminate it with a semicolon.

Commenting Code

Code comments in ColdFusion scripting differ from those in tag-based code, as shown in Listing 44.3.

Listing 44.3. CommentingCode.cfm—Comparing Code Comments in Script vs. Tags

<!--- Author: Adam Phillip Churvis -- ProductivityEnhancement.com --->
<!--- Types of comments --->

<!--- Tag-based single-line comment before code block --->
<cfset example = "before block">

<cfset example = "inline"> <!--- Tag-based single-line comment after code--->

<!--- Tag-based
multi-line comment --->
<cfset example = "multi-line">

<cfscript>
  // Script-based single-line comment before code block
  example = "before block";

  example = "inline"; // Script-based single-line comment after code

  /* Script-based
  multi-line comment */
  example = "multi-line";
</cfscript>

Calling ColdFusion Functions

Calling a ColdFusion function in script is just like assigning a static value to a variable—you’re just assigning the result of a function call instead of a static value. Take a look at Listing 44.4.

Listing 44.4. ColdFusionFunctions.cfm—Calling ColdFusion Functions from ColdFusion Script

<!--- Author: Adam Phillip Churvis -- ProductivityEnhancement.com --->
<!--- Calling ColdFusion functions within cfscript --->

<cfscript>
  todaysDate = Now();
  dateDisplay = "The date is #DateFormat(todaysDate, 'dddd, mmmm d, yyyy')#
    and the time is " & TimeFormat(todaysDate, 'h:mm tt');
</cfscript>

<cfoutput>#dateDisplay#</cfoutput>

Flow Control Using <cfscript>

As already mentioned, there are some important differences between how CFML and <cfscritp> perform similar operations. Now let’s see how those differences manifest in actual code.

if-elseif-else Constructs

If-else constructs are used to control flow based on a single test, and if-elseif-else constructs are used to control flow based on multiple tests. In Listing 44.5, the first test is based on the value of colorCode, and the second test is based on the value of temperature. If both of those tests are false, then control flows to the else clause.

Listing 44.5. IfElseifElse.cfm—Deciding Flow Based on Multiple Tests

<!--- Author: Adam Phillip Churvis -- ProductivityEnhancement.com --->
<!--- If-Elseif-Else --->
<!--- Call this page using various URL values for colorCode and emergency --->
<cfparam name="url.term" default="red">
<!--- Tag-based --->
<cfif URL.colorCode EQ "Red">
  <cfset result = "Emergency">
<cfelseif URL.temperature GTE "100">
  <cfset result = "Hot">
<cfelse>
  <cfset result = "Normal">
</cfif>

<cfscript>
  // Script-based
  if(URL.colorCode == "Red") {
    result = "Emergency";
  } else if(URL.temperature >= "100") {
    result = "Hot";
  } else {
    result = "Normal";
  }
</cfscript>

<cfoutput>#result#</cfoutput>

Try using these URLs to see how Listing 44.5 reacts:

   <!--- Displays "Emergency" --->
   http://localhost:8500/chapter44/ifelseifelse.cfm?colorcode=red

   <!--- Displays "Normal" --->
   http://localhost:8500/chapter44/ifelseifelse.cfm?colorcode=blue&temperature=72

   <!--- Displays "Hot" --->
   http://localhost:8500/chapter44/ifelseifelse.cfm?colorcode=green&temperature=115

Also try commenting and uncommenting the script-based and syntax-based sections of code to see that each section works exactly the same.

Whenever you have more than one test that controls the flow of logic, you’ll use an if-elseif-else construct. Don’t confuse multiple tests with multiple results from a single test, though. That sort of flow control is best handled by a switch-case construct, which is discussed next.

switch-case Constructs

If you have a single test that can have an enumerated set of results (in other words, a specific set of predefined result values), and these results need to control the flow of logic, then you’ll use a switch-case statement, as in Listing 44.6.

Listing 44.6. SwitchCase.cfm—Deciding Flow Based on a Single Test with Enumerated Results

<!--- Author: Adam Phillip Churvis -- ProductivityEnhancement.com --->
<!--- Switch-Case --->

<!--- Tag-based --->
<cfset status = "Moderate">
<cfswitch expression="#status#">
  <cfcase value="Low">
    <cfset score = 25>
  </cfcase>
  <cfcase value="Subnormal,Moderate,Elevated">
    <cfset score = 50>
  </cfcase>
  <cfcase value="High">
    <cfset score = 75>
  </cfcase>
  <cfdefaultcase>
    <cfset score = 0>
  </cfdefaultcase>
</cfswitch>

<cfscript>
  // Script-based
  status = "Moderate";
  switch(status) {
    case "Low":
      score = 25;
      break;

    case "Subnormal":
    case "Moderate":
    case "Elevated":
      score = 50;
      break;

    case "High":
      score = 75;
      break;

    default:
      score = 0;
  }
</cfscript>

<cfoutput><p>#score#</p></cfoutput>

Notice that there are more case statements in the script version than in the tag-based version. One of the useful features of the <cfcase> tag is that you can specify a comma-separated list of values to satisfy a case. Unfortunately, this isn’t possible with the script version because it follows the JavaScript model of fall-through and breaks.

Fall-through is a feature that causes code to continue executing until a break statement is reached. For example, the second, third, and fourth case statements in Listing 44.6 are all grouped together. So if the value of status is Subnormal, flow of control will begin at that case statement and then continue executing lines of code until a break statement is reached. This means the next line of code to execute would be case "Moderate":, which wouldn’t do anything; then case "Elevated":, which also wouldn’t do anything; and then score = 50;, which would assign 50 to the score variable. Finally, the break; line would be processed, and flow of control would pass to the end of the switch construct and then continue to the <cfoutput> line.

So as you start writing switch-case constructs in ColdFusion scripting, make sure to include a break; statement at the end of each case (except the default case, which is at the end of the switch construct and so doesn’t need a break).

Loops

Of course, no scripting language would be complete without ways to place a chunk of code into a loop of some kind. ColdFusion scripting provides for four types of loops: for, while, do-while, and for-in. Unfortunately, ColdFusion scripting doesn’t provide for query loops or list loops.

for Loops

for loops execute a block of script a predetermined number of times and use a numerical index as a starting point. This index is incremented or decremented with each iteration of the loop, and looping continues until the index reaches the ending value. Listing 44.7 demonstrates a typical for loop.

Listing 44.7. ForLoops.cfm—Looping a Predetermined Number of Times

<!--- Author: Adam Phillip Churvis -- ProductivityEnhancement.com --->
<!--- Edited by: Charlie Arehart, carehart.org --->
<!--- For loop (used when you can determine the number of loops beforehand) --->

<!--- Tag-based --->
<cfset colorCodes = ["Red,Orange,Yellow"]>
<cfloop index="i" from="1" to="#ArrayLen(colorCodes)#">
  <cfoutput><p>#colorCodes[i]#</p></cfoutput>
</cfloop>

<cfscript>
  // Script-based
  colorCodes = ["Red,Orange,Yellow"];
  for(i=1; i LTE ArrayLen(colorCodes); i=i+1) {
    WriteOutput("<p>" & colorCodes[i] & "</p>");
  }
</cfscript>

for loops can be used to loop over the items in a list; the number of iterations is simply the result of the function ListLen().

while Loops

while loops execute a block of script as long as a condition is true. When the condition is no longer true, the loop exits. Listing 44.8 shows how a while loop could be used.

Listing 44.8. WhileLoops.cfm—Looping While a Condition Is True

<!--- Author: Charlie Arehart -- carehart.org --->
<!--- While loop (used when the number of loops depends on a condition) --->

<!--- Tag-based --->
<cfset rate=5>
<cfset init = 1>
<cfset total = init>
<cfset years = 0>
<cfloop condition="total lt 2">
   <cfset total = total + (total*rate/100)>
   <cfset years++>
</cfloop>
<cfoutput>At a rate of %#rate# interest, it will take #years# years for $#init# to
at least double, to #dollarformat(total)#</cfoutput><p>

<cfscript>
  // Script-based
  rate=5;
  init = 1;
  total = init;
  years = 0;
  while(total lt 2) {
    total = total + (total*rate/100);
    years++;
  }
  writeoutput("At a rate of %#rate# interest, it will take #years# years for $#init#
to at least double, to #dollarformat(total)#");
</cfscript>

while loops are most often used when you don’t know how many times a loop should iterate—or whether the loop should iterate at all—but you can formulate an expression that, while true, permits the loop to iterate. If you attempt to enter a while loop while the expression evaluates to false, the loop will never iterate at all.

do-while Loops

Unlike while loops, do-while loops always iterate at least once. This occurs because the while condition’s expression is evaluated at the end of each iteration rather than before, and if the condition defined in the while clause is false, the loop exits. Otherwise, the loop continues while the condition is true. In Listing 44.9, we create a typical do-while loop.

Listing 44.9. DoWhileLoops.cfm—Looping At Least Once and While a Condition Is True

<!--- Author: Charlie Arehart -- carehart.org --->
<!--- Do-While loop (a conditional loop that will iterate at least once) --->

<!--- Tag-based --->
<!--- (There is no tag-based equivalent to a do-while loop) --->

<cfscript>
  // Script-based
  // Calculates factorial of counter (eg, for 4, caclulate 4 * 3 * 2 * 1)
  counter=4;
  factorial=1;
  do {
    factorial = factorial * counter ;
    counter--;
  } while(counter > 0);
  writeoutput (factorial);
</cfscript>

do-while loops are most often used in scenarios where you are certain to perform an operation on a nonempty value or set of elements, and each iteration of the loop may affect the number remaining in the set. Notice that the above code would have executed even if the starting counter value was 0, in which case factorial would be set (correctly) to 0.

for-in Loops

for-in loops iterate through a block of script once for every item in a structure and populate a local variable with the name of the key of the current item. Once every item in the structure has been looped through, the loop exits. Listing 44.10 demonstrates how a for-in loop iterates over a ColdFusion structure.

Listing 44.10. ForInLoops.cfm—Looping Over the Keys in a Structure

<!--- Author: Adam Phillip Churvis -- ProductivityEnhancement.com --->
<!--- Edited by: Charlie Arehart, carehart.org --->
<!--- For-In loop (used to loop over a structure or "collection") --->

<!--- Tag-based --->
<cfset player = {name="John Doe", age="27", gender="Male"}>
<cfloop collection="#player#" item="keyName">
  <cfoutput><p>#keyName#: #player[keyName]#</p></cfoutput>
</cfloop>

<cfscript>
  // Script-based
  player = {name="John Doe", age="27", gender="Male"};
  for(keyName in player) {
    WriteOutput("<p>#keyName#: #player[keyName]#</p>");
  }
</cfscript>

for-in loops are useful for testing or summarizing the values of keys in a structure. This comes in handy when you consider that ColdFusion variable scopes are all structures.

Using continue and break

Sometimes you may want to abort a particular iteration of a loop without aborting the loop itself—in other words, you want to skip the remaining code in the current iteration and continue at the beginning of the next iteration of the loop. Other times, your logic may encounter a condition that requires you to break out of the loop completely. ColdFusion scripting easily handles both of these situations (whereas tag-based code can directly handle only breaking out of a loop).

Listing 44.11 loops over an array of quantities in a shopping cart. If a quantity is less than 100, there is no wholesale discount applied, so the line of code that outputs the wholesale discount message is skipped by the continue statement. Likewise, if someone attempts to order more than 10,000 of any given item, the shopping cart is considered invalid and the flow of logic breaks out of the loop entirely. Notice also that there is no tag-based equivalent to continue.

Listing 44.11. ContinueAndBreak.cfm—Skipping Iterations and Breaking Out of a Loop

<!--- Author: Adam Phillip Churvis -- ProductivityEnhancement.com --->
<!--- Break and Continue --->

<!--- Tag-based --->
<!--- (There is no tag-based equivalent to Continue, so we'll kludge one) --->
<cfset quantityOrdered = [16,400,25000,47]>
<cfloop index="i" from="1" to="#ArrayLen(quantityOrdered)#">
  <cfset continue = FALSE>
  <cfoutput><p>Quantity ordered: #quantityOrdered[i]#</p></cfoutput>
  <cfif quantityOrdered[i] LTE 100>
    <cfset continue = TRUE>
  </cfif>

  <cfif NOT continue>
    <cfif quantityOrdered[i] GT 10000>
      <p>You cannot request more than 10000 items per order.</p>
      <p>Order terminated.</p>
      <cfbreak>
    </cfif>

    <p>(wholesale discount will be applied to previous item)</p>
  </cfif>
</cfloop>

<cfscript>
  // Script-based
  quantityOrdered = [16,400,25000,47];
  for(i = 1; i <= ArrayLen(quantityOrdered); i++) {
    WriteOutput("<p>Quantity ordered: #quantityOrdered[i]#</p>");
    if(quantityOrdered[i] <= 100) {
      continue;
    }

    if(quantityOrdered[i] > 10000) {
      WriteOutput("<p>You cannot request more than 10000 items per order.</p>");
      WriteOutput("<p>Order terminated.</p>");
      break;
    }
    WriteOutput("<p>(wholesale discount will be applied to previous item)</p>");
  }
</cfscript>

Notice the rather clumsy way we had to handle “continuing” in the tag-based version? Good enough reason to use scripting rather than tags for such a loop.

3. Common Problems and Solutions | Next Section Previous Section

There are currently no related articles. Please check back later.