Skip to content

Instantly share code, notes, and snippets.

@learncfinaweek
Created November 20, 2012 21:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save learncfinaweek/4121109 to your computer and use it in GitHub Desktop.
Save learncfinaweek/4121109 to your computer and use it in GitHub Desktop.
Looping

Looping is employed by programming languages to repeat a behavior defined by a section of code either while a condition is maintained true (conditional looping), or a certain number of times (iterative looping). As with other programming languages, ColdFusion allows you to perform both iterative and conditional looping.

ColdFusion uses the cfloop tag to enable looping in tag-based syntax. cfloop permits you to loop over a variable such as a structure or array, loop while a condition remains true, or loop for a given iteration. ColdFusion permits looping in cfscript using for loops and do while loops.

Tag-based Looping

It is easiest to demonstrate looping by example. Consider the following code:

<cfloop from="1" to="5" index="i">
	#i#<br />
</cfloop>

The code above performs an iterative loop. The from attribute specifies the start value, while the to attribute specifies the end value. By default, cfloop will increment by 1 each iteration. You can override this behavior using the step attribute, which can be any positive or negative number. This means you can also decrement the loop’s index by specifying -1 for the step attribute. The index attribute stores the current index value of the loop. This is the value that increments on each execution. The iterative loop will continue execution until the index reaches the max value as specified by the to attribute. It is important to note that the loop will execute while the index is equal to the maximum value, but then exit. This means the output from the code above is:

1
2
3
4
5 <- notice that the loop executed while the index was equal to the maximum value

Iterative looping generally uses variables to specify the bounds of the iteration, unlike the example above. A great example of this is looping over an array. Until CF9, we could only loop over an array through the use of iterative looping as shown below. This case is still useful today, especially when you need to keep track of the current index as well as the array value. The important thing to keep in mind is that ColdFusion arrays are 1-indexed instead of 0-indexed as with some other programming languages. This means we have to start our loop counter at 1 when looping over an array.

<cfset myArray = ['Jeff', 'John', 'Steve', 'Julianne'] />

<cfloop from="1" to="#arrayLen(myArray)#" index="i">
	#i#: #myArray[i]#<br />
</cfloop>

For the upper limit of this iterative loop, we are passing in a variable equal to the present size of our array. This loop will execute the code within the cfloop block one time for each value in the array. The output when running the code above is:

1: Jeff
2: John
3: Steve
4: Julianne

CF9 and above allows us to loop over an array using shorthand. This is useful when you only need the data contained within the array, but do not need the associated index.

<cfloop array="#myArray#" index="item">
	#item#<br />
</cfloop>

Don’t let the index attribute fool you; the index that is returned is not an index, but rather the data contained within the array at the current index. We no longer have a reference to the array index itself. The output when running the code above is:

Jeff
John
Steve
Julianne

cfloop permits the developer to loop over a list. The list datatype, as we learned earlier, is a delimited String. ColdFusion understands that the string is delimited and provides special functions for the list. A list loop is displayed in the code below:

<cfset myList = 'Jeff,John,Steve,Julliane' />
<cfloop list="#myList#" index="item">
	#item#<br />
</cfloop>

If you need to keep track of the index as opposed to just the value of the current item position, you can use a standard iterative loop:

<cfloop from="1" to="#listlen(myList)#" index="i">
	#i#: #listGetAt(myList, i)#<br />
</cfloop>

Another neat trick you can use in a list loop is by using the delimiters attribute. You can specify multiple delimiters as well. The following example allows you to break down a string into individual words:

<cfset myList = "This is the test sentence" />
<cfloop list="#myList#" index="word" delimiters=" ">
	#word#<br />
</cfloop>

The output from the code above is:

This
is
a
test
sentence

ColdFusion also allows you to loop over the items in a collection (structure) one iteration per key. Using associative array notation, you can get the value for each key in a structure.

<cfset myStruct = { name= 'Jeff Katersian', id= 12445, dob= '1/2/1994' } />

<cfloop collection="#myStruct#" item="key">
 #key#: #myStruct[key]#<br />
</cfloop>

The code above results in the following output:

NAME: Jeff Katersian
DOB: 1/2/1994
ID: 12445

ColdFusion allows you to loop over the contents of a query using cfloop as well. The loop will execute the code inside the cfloop tag one time per query row.

<cfscript>
	myQuery = queryNew("id,user");
	queryAddRow(myQuery);
	querySetCell(myQuery, 'id', '1');
	querySetCell(myQuery, 'user', 'Jeff');
	queryAddRow(myQuery);
	querySetCell(myQuery, 'id', '2');
	querySetCell(myQuery, 'user', 'John');
	queryAddRow(myQuery);
	querySetCell(myQuery, 'id', '3');
	querySetCell(myQuery, 'user', 'Steve');
</cfscript>

<cfloop query="myQuery">
	#myQuery.id# #myQuery.user#<br />
</cfloop>

Unlike the other loops, the query attribute takes a pointer to the query as opposed to the value itself (we specified the name of the query as opposed to supplying #myQuery#). The code above results in the following output:

1 Jeff
2 John
3 Steve

cfloop can be used to perform conditional looping as well as the item and iterative loops demonstrated above. Conditional looping will execute the code within the body of a cfloop as long as a condition evaluates to true. In the following example, we loop over an array as long as it contains items.

<cfset myArray = ['Jeff', 'John', 'Steve', 'Julianne'] />

<cfloop condition="#arrayLen(myArray)#">
	Current length = #arrayLen(myArray)#<br />
	<cfset arrayDeleteAt(myArray, 1) />
</cfloop>

Remember in the Decision Making chapter that ColdFusion is dynamically typed, so any positive integer will evaluate to the Boolean value of true. As long as the condition remains true (that the array has a length), the loop will continue to execute. As soon as the condition is false, the loop will stop executing. We will never receive an error from this loop that the array contains no items, since it will not execute if the condition is not true.

Important Note: If the upper limit of the iterative loop is never reached, or a condition never becomes false in a conditional loop, an infinite loop condition can occur. This simply means that your loop will never finish and program execution will continue forever until the thread runs out of memory. This condition will result in Java heap space error, or a timeout error.

cfscript Looping

Almost all of the same loop constructs are permitted in cfscript as are available in CFML. Common cfscript loops are demonstrated below.

Iterative Loop over an Array

for (i=1;i<=arrayLen(myArray);i++) {
	writeOutput('#i#: #myArray[i]#<br />');
}

Array Loop

for (item in myArray) {
	writeOutput(#item# & '<br />');
}

Loop over a Collection (Structure)

for ( key in myStruct) {
	writeOutput('#key#: #myStruct[key]#<br />');
}

Loop over a Query (CF9 and Below)

for ( i=1;i<=myQuery.recordCount;i++ ) {
	writeOutput('#myQuery.id#: #myQuery.user[i]#<br />');
}

Loop over a Query (CF10+)

for ( row in myQuery ) {
	writeOutput('#row.id#: #row.user#');
}	

Flow Control Inside of cfloop

Sometimes it is necessary to end a loop before the condition for loop termination is met. ColdFusion allows this in CFML via the cfbreak tag and in cfscript using the break keyword. A simple example is provided below:

<cfloop from="1" to="5" index="i">
	#i#<br />
	<cfbreak />
</cfloop>

The output from the code above is:

1

There are also times when you want to skip processing the current iteration of a loop, perhaps based on a condition, and then continue looping as normal. As of CF9, you can use the cfcontinue tag to perform this logic. In cfscript (across versions) you can use the continue keyword. An example is provided below:

<cfloop from="1" to="5" index="i">
	<cfif i MOD 2 EQ 0>
		<cfcontinue />
	</cfif>
	#i#<br />
</cfloop>

The code above results in the following output:

1
3
5

Additional Looping

ColdFusion also allows you to loop over files and date/time types. For more information visit:

@displague
Copy link

It would be nice to demonstrate a while(){} loop.

@shaedrich
Copy link

Hey, I found a small mistake:

Instead of highlighting statement you should hightlight continue in line 283 ("In cfscript (across versions) you can use the continue keyword").

Best regards

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment