ColdFusion 10 - Looping Over Queries Using A For-In Loop In CFScript

Posted April 19, 2012 at 9:35 AM by Ben Nadel

Tags: ColdFusion

Yesterday, I campaigned against using ColdFusion 10's dynamic "query" attribute in the CFLoop tag. That said, I am really excited that CFScript now supports FOR-IN looping for queries. This creates complete uniformity in CFScript for looping over queries, arrays, and structs. And, it definitely makes looping over queries in CFScript much easier and far more intuitive than the index-based looping that was previously required.

NOTE: At the time of this writing, ColdFusion 10 was in public beta.

To quickly demonstrate this new features, I am going to build up a new query and then loop over it using a FOR-IN loop. In the following code, you'll notice that you can still access query meta-data (recordCount and currentRow) using the query object:

  • <cfscript>
  •  
  •  
  • // Build up a new query. Notice that we are using the augmented
  • // features of ColdFusion 10 and the queryNew() to build complex
  • // queries in one command.
  • friends = queryNew(
  • "id, name",
  • "cf_sql_integer, cf_sql_varchar",
  • [
  • [ 1, "Tricia" ],
  • [ 2, "Sarah" ],
  • [ 3, "Joanna" ]
  • ]
  • );
  •  
  •  
  • // The query object now supports FOR-IN iteration in CFScript. We
  • // can iterate over the query, row by row.
  • for (friend in friends){
  •  
  • // When iterating over a query in CFScript, you can use the
  • // main query object to get meta-data; then, use the row
  • // object to get row-specific properties.
  • writeOutput(
  • "[ #friends.currentRow# of #friends.recordCount# ] " &
  • friend.name &
  • "<br />"
  • );
  •  
  • }
  •  
  •  
  • </cfscript>

As you can see, each row of the query is presented as a struct in which the column names have become struct keys. This makes looping and outputting query data very easy! When we run the above code, we get the following output:

[ 1 of 3 ] Tricia
[ 2 of 3 ] Sarah
[ 3 of 3 ] Joanna

With this level of ease, I can't see much of a use for ever converting a query object to another kind of object (except maybe for with API return data). But, with the way query-iteration now works, you can see that converting a query object to an array-of-structs can be incredibly straightforward - the query iteration is already doing have the work for you:

  • <cfscript>
  •  
  •  
  • // Build up a new query. Notice that we are using the augmented
  • // features of ColdFusion 10 and the queryNew() to build complex
  • // queries in one command.
  • friends = queryNew(
  • "id, name",
  • "cf_sql_integer, cf_sql_varchar",
  • [
  • [ 1, "Tricia" ],
  • [ 2, "Sarah" ],
  • [ 3, "Joanna" ]
  • ]
  • );
  •  
  •  
  • // I convert the given query to an array of structs.
  • function queryToArray( query ){
  •  
  • // Define our array to hold the row data for the query.
  • var queryAsArray = [];
  •  
  • // Iterate over the query using a FOR-IN construct. This will
  • // automatically convert each row to a struct. At that point,
  • // all we have to do is collect it.
  • for (var row in query){
  •  
  • // Add the row-as-struct to our array.
  • arrayAppend( queryAsArray, row );
  •  
  • }
  •  
  • // Return the query collection as an array.
  • return( queryAsArray );
  •  
  • }
  •  
  •  
  • // Iterate over the query as an array. Since we are using the
  • // arrayEach() method, we lose track of the current row and
  • // the recordCount.
  • arrayEach(
  • queryToArray( friends ),
  • function( friend ){
  •  
  • // Here, each "friend" is the struct produced by the
  • // FOR-IN iteration above.
  • writeOutput( friend.name & "<br />" );
  •  
  • }
  • );
  •  
  •  
  • </cfscript>

Here, we've created a function - queryToArray() - that simply collects the structs produced by each row-iteration and appends them to an array. Then, we iterate over the array using ColdFusion 10's new arrayEach() method and get the following output:

Tricia
Sarah
Joanna

As I said before, ColdFusion 10 is really the version of ColdFusion that makes CFScript look really appealing to me. Up until now, I've been a strong proponent of ColdFusion tags for everything; but, CFScript is really maturing to the point where I can imagine using it on a regular basis.


You Might Also Be Interested In:



Reader Comments

Apr 19, 2012 at 9:47 AM // reply »
24 Comments

Hey Ben...you've got a typo in the first para. "perviously required".


Apr 19, 2012 at 9:49 AM // reply »
26 Comments

We agree on this one :)

Great addition.


Apr 19, 2012 at 9:53 AM // reply »
17 Comments

I love using the for-in clause now in cfscript! Except when looping over component metadata.
Silly things claim to be arrays when they aren't really, and thus break for-in, at least in cf9, haven't tried 10.


Apr 19, 2012 at 10:02 AM // reply »
11,238 Comments

@Andy,

Ah, good catch! Should be fixed upon next cache-clear.

@Sam,

Ha ha, high-five :)

@Jim,

Yeah, I'm definitely loving the uniformity now of the script-based looping. That's really weird about the metadata, though. Maybe it's some weird Java object that is confusing the engine? Very strange.


Apr 19, 2012 at 10:18 AM // reply »
17 Comments

@Ben

Yeah, when using getComponentMetaData() or getMetaData(), it treats parameters as an an array during a writeDump() (possibly functions as well, i forget now), and you can iterate over them with a normal for loop. But when you try to use for-in, it throws something about trying to reference a complex object as a scalar or something and lists it as a java object.

As an aside since it's related, I'm using railo as a place holder until cf10 comes out. Been going through and converting cfcs to cfscript only versions, using your example for metadata in the /** **/ blocks.

Railo doesn't support metadata (or the accessors flag, or a bunch of other things) in those blocks and forces me list them in the method declaration. According to bug reports, Railo doesn't seem inclined to support this functionality due to semi-justifiable language politics, but that argument falls flat when you look at how C# does webmethods.

Was having a fun time with Railo too until I hit this, now i'm dumping it into waste bin of "meh" could-have-beens. Guess thats what I get for experimenting.

CF10 needs to hurry up and drop so I can spend budget monies on it!


Apr 19, 2012 at 10:21 AM // reply »
17 Comments

@Ben

Might want to double check your code for sending out comment posts, getting a profile pic that is clearly not your font of manliness on your posts.


Apr 19, 2012 at 10:29 AM // reply »
26 Comments

@Jim,

"But when you try to use for-in, it throws something about trying to reference a complex object as a scalar or something and lists it as a java object"

99% sure that is fixed in CF10.

Its an annoying bug for sure.


Apr 19, 2012 at 10:49 AM // reply »
11,238 Comments

@Jim,

Sounds really strange. Out of curiosity, what are you using the metadata for? Sounds like you're really digging into it.

@Sam,

That's good to hear!


Apr 19, 2012 at 12:09 PM // reply »
17 Comments

@Ben
I'm updating my ExtDirect stack that supports persistent namespaces for invoking components to the latest ExtDirect spec that supports named arguments.

Thus, as I'm adding components to my registry, instead of just counting the number of required arguments, I'm now tracking named optional and required arguments so that when named arguments are used by ExtDirect, I can ensure the argument collection for requireds is fully populated or not, and handle accordingly.

Once I get that done, I'm adding support to the stack to prevent possible CSRF attacks from the AJAX side of ExtJS.


Apr 20, 2012 at 3:11 AM // reply »
1 Comments

Nice.
Would be glad to see the "item" attribute added to CFLOOP QUERY in CF10. Than you have both: the for-in-loop as in script and you can use a dynamic QUERY attribute without scoping trouble ;-)


son
Jun 15, 2012 at 6:46 PM // reply »
1 Comments

SSD Web Solutions provides domain
registration, web hosting and bulk sms services to small businesses. We
provide web hosting on both platform windows hosting and linux hosting. We
do also provide bulk voice calls for promotional calls to India. To find out more information, go visit: http://www.ssdindia.com/


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 17, 2013 at 7:42 PM
HashKeyCopier - An AngularJS Utility Class For Merging Cached And Live Data
Ben - thanks so much for posting these Angular articles and findings, they've been a huge help towards learning one of the more 'complex' JavaScript frameworks out there (IMO). I have been using Angu ... read »
May 16, 2013 at 5:01 PM
UPDATE: Parsing CSV Data Files In ColdFusion With csvToArray()
Your code was the closest thing I've found to obtaining some direction for converting ISO fields to values that CF can translate properly. Thank you for posting! ... read »
May 15, 2013 at 10:37 PM
Very Simple Pusher And ColdFusion Powered Chat
hi id making plz easy ... read »
May 15, 2013 at 6:07 PM
Making SOAP Web Service Requests With ColdFusion And CFHTTP
Ben, you once again saved my bacon at work. Thank you, thank you, thank you! ... read »
May 15, 2013 at 4:15 PM
What If All User Interface (UI) Data Came In Reports?
@Josh, Thanks! @Ben, I definitely recommend the David West book "Object Thinking" I've been quoting from. It goes deeply into the philosophy and history of OO programming. His breadth ... read »
May 15, 2013 at 11:36 AM
Ask Ben: Print Part Of A Web Page With jQuery
I found this helpfull when you need to keep (refresh) the original parent page after closing the iframe child print dialog (Hoping you're not using a form at this time so it won't submit again): On ... read »
May 14, 2013 at 7:13 PM
What If All User Interface (UI) Data Came In Reports?
@Jonah, If there's any books you'd recommend on the subject of domain modelling, I'd love to hear it. I just downloaded the free PDF of "Domain Driven Design Quickly". Figured I'd give it ... read »
May 14, 2013 at 6:57 PM
The UX Of Prototyping: Low-Fidelity Is The New High-Fidelity
@Phillip, I'm not sure I follow what you mean? Are you saying that you looked at the list of widgets provided by the jQuery UI and let that be your style guide? ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools