Implementing cfscript


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 12.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 12.2. CreatingVariables.cfmCreating 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 = ArrayNew(1)> <cfset gameScores[1] = "93"> <cfset gameScores[2] = "87"> <cfset gameScores[3] = "96"> <!--- A structure ---> <cfset player = StructNew()> <cfset player.name = "John Doe"> <cfset player.age = "27"> <cfset player.gender = "Male"> <cfscript>   // A simple variable   welcomeMessage = "Welcome to ColdFusion scripting!";      // An array   gameScores = ArrayNew(1);   gameScores[1] = "93";   gameScores[2] = "87";   gameScores[3] = "96";      // A structure   player = StructNew();   player.name = "John Doe";   player.age = "27";   player.gender = "Male"; </cfscript> <p><cfoutput>#welcomeMessage#</cfoutput></p> <p><cfdump var="#gameScores#" label="gameScores"></p> <p><cfdump var="#player#" label="player"></p> 

Running Listing 12.2 produces the output shown in Figure 12.1.

Figure 12.1. The output from Listing 12.2.


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 12.3.

Listing 12.3. CommentingCode.cfmComparing 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> 

NOTE

Don't feel embarrassed when your script breaks because you accidentally put a tag-based comment inside your <cfscript> code. We've all done it more times than we care to admit.


Calling ColdFusion Functions

Calling a ColdFusion function in script is just like assigning a static value to a variableyou're just assigning the result of a function call instead of a static value. Take a look at Listing 12.4.

Listing 12.4. ColdFusionFunctions.cfmCalling 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>

We gave an introduction to the generic differences between flow control in scripting and tags in Table 12.1. 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 12.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 12.5. IfElseifElse.cfmDeciding 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 ---> <!--- 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 EQ "Red") {     result = "Emergency";   } else if(URL.temperature GTE "100") {     result = "Hot";   } else {     result = "Normal";   } </cfscript> <cfoutput>#result#</cfoutput> 

Try using these URLs to see how Listing 12.5 reacts:

 <!--- Displays "Emergency" ---> http://localhost/chapter12/ifelseifelse.cfm?colorcode=red <!--- Displays "Normal" ---> http://localhost/chapter12/ifelseifelse.cfm?colorcode=blue&temperature=72 <!--- Displays "Hot" ---> http://localhost/chapter12/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 12.6.

Listing 12.6. SwitchCase.cfmDeciding 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 12.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 12.7 demonstrates a typical for loop.

Listing 12.7. ForLoops.cfmLooping a Predetermined Number of Times
 <!--- Author: Adam Phillip Churvis -- ProductivityEnhancement.com ---> <!--- For loop (used when you can determine the number of loops beforehand) ---> <!--- Tag-based ---> <cfset colorCodes = ArrayNew(1)> <cfset colorCodes[1] = "Red"> <cfset colorCodes[2] = "Orange"> <cfset colorCodes[3] = "Yellow"> <cfloop index="i" from="1" to="#ArrayLen(colorCodes)#">   <cfoutput><p>#colorCodes[i]#</p></cfoutput> </cfloop> <cfscript>   // Script-based   colorCodes = ArrayNew(1);   colorCodes[1] = "Red";   colorCodes[2] = "Orange";   colorCodes[3] = "Yellow";   for(i=1; i LTE ArrayLen(colorCodes); i=i+1) {     WriteOutput("<p>" & colorCodes[i] & "</p>");   } </cfscript> 

for loops are often used to loop over the elements of an array; the number of iterations is simply the result of the function ArrayLen(). Since there is no scripting equivalent of list loops or query loops, many developers use a for loop to loop over a query's rows or a list's elements.

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 12.8 shows how a typical while loop works.

Listing 12.8. WhileLoops.cfmLooping While a Condition Is True
 <!--- Author: Adam Phillip Churvis -- ProductivityEnhancement.com ---> <!--- While loop (used when the number of loops depends on a condition) ---> <!--- Tag-based ---> <cfset colorCodes = ArrayNew(1)> <cfset colorCodes[1] = "Red"> <cfset colorCodes[2] = "Orange"> <cfset colorCodes[3] = "Yellow"> <cfset i = "1"> <cfloop condition="i LTE ArrayLen(colorCodes)">   <cfoutput><p>#colorCodes[i]#</p></cfoutput>   <cfset i = i + 1> </cfloop> <cfscript>   // Script-based   colorCodes = ArrayNew(1);   colorCodes[1] = "Red";   colorCodes[2] = "Orange";   colorCodes[3] = "Yellow";   i = 1;   while(i LTE ArrayLen(colorCodes)) {     WriteOutput("<p>" & colorCodes[i] & "</p>");     i = i + 1;   } </cfscript> 

while loops are most often used when you don't know how many times a loop should iterateor whether the loop should iterate at allbut 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 12.9, we create a typical do-while loop.

Listing 12.9. DoWhileLoops.cfmLooping At Least Once and While a Condition Is True
 <!--- Author: Adam Phillip Churvis -- ProductivityEnhancement.com ---> <!--- 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   colorCodes = ArrayNew(1);   colorCodes[1] = "Red";   colorCodes[2] = "Orange";   colorCodes[3] = "Yellow";   i = 1;   do {     WriteOutput("<p>" & colorCodes[i] & "</p>");     i = i + 1;   } while(i LTE ArrayLen(colorCodes));      // This loop would have thrown an exception if the array contained no elements </cfscript> 

do-while loops are most often used in scenarios where you are certain to perform an operation on a nonempty set of elements, and each iteration of a loop may affect the evaluation of the condition being tested. Notice that the above code would have failed if the array had been empty.

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 12.10 demonstrates how a for-in loop iterates over a ColdFusion structure.

Listing 12.10. ForInLoops.cfmLooping Over the Keys in a Structure
 <!--- Author: Adam Phillip Churvis -- ProductivityEnhancement.com ---> <!--- For-In loop (used to loop over a structure or "collection") ---> <!--- Tag-based ---> <cfset player = StructNew()> <cfset player.name = "John Doe"> <cfset player.age = "27"> <cfset player.gender = "Male"> <cfloop collection="#player#" item="keyName">   <cfoutput><p>#keyName#: #player[keyName]#</p></cfoutput> </cfloop> <cfscript>   // Script-based   player = StructNew();   player.name = "John Doe";   player.age = "27";   player.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 itselfin 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 12.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 12.11. ContinueAndBreak.cfmSkipping 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 = ArrayNew(1)> <cfset quantityOrdered[1] = "16"> <cfset quantityOrdered[2] = "400"> <cfset quantityOrdered[3] = "25000"> <cfset quantityOrdered[4] = "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 = ArrayNew(1);   quantityOrdered[1] = "16";   quantityOrdered[2] = "400";   quantityOrdered[3] = "25000";   quantityOrdered[4] = "47";   for(i = 1; i LTE ArrayLen(quantityOrdered); i=i+1) {     WriteOutput("<p>Quantity ordered: #quantityOrdered[i]#</p>");     if(quantityOrdered[i] LTE 100) {       continue;     }          if(quantityOrdered[i] GT 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.



Advanced Macromedia ColdFusion MX 7 Application Development
Advanced Macromedia ColdFusion MX 7 Application Development
ISBN: 0321292693
EAN: 2147483647
Year: 2006
Pages: 240
Authors: Ben Forta, et al

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net