Let SQL Do The Data Work

Many come to ColdFusion from HTML development and find out that CF is great for putting data into their beautiful web pages. The natural tendency is to select all the database and dump it into the page. As the data grows, the new developer will pick up some SQL skills to filter the list down and even do some grouping of data and then output it nicely on the page. ColdFusion does this well with its CFOUTPUT attribute GROUP. This is all just wonderful.

Then a requirement comes along. Our aspiring developer then figures out he can use CFLOOPS and CFIF statements to control the output with even more but he notices his code is getting messy and pages are loading more slowly. He is sensing that he might be asking ColdFusion to do things the database server is better suited for. He is right.

A good practice in web application development is to separate the data manipulation from the data presentation. Database servers are designed to crunch data efficiently and have functions built in to do most if not all of the data manipulation. A developer should strive to have the data all crunched and manipulated before it is presented back to ColdFusion for presentation.

I was recently asked by someone online how they could get maximum value from a group of items with the same id. This would be like finding the top sales rep where the database table (monthly_sales) has the region id (id) and the sales dollars (sales). A developer could query the database for all records for the month and sort by sales dollars and id and then loop through the results and use CFSET and CFIF to out put only the first sales rep in each region. This would be asking the database to send back more data then necessary and would be asking ColdFusion to a little too much crunching.

I thought about this problem for a bit and decided to use SELECT DISTINCT which brought back distinct items if I queried one column. But I was querying two columns so the database would return distinct combinations. I need to get each distinct ID and the maximum dollars so I used DISTINCT along with the MAX function. Here's my SQL that brought back each individual id along with the maximum dollars for each.

SELECT DISTINCT id, MAX(sales) AS sales_dollars FROM monthly_sales GROUP BY id

The moral of the story is that you should get the database to do all the data work and have ColdFusion present the data.

CFDUMP even better in CF8

The CFDUMP tag allows you to get the elements, variables, and values of most kinds of ColdFusion scopes or objects. It's been a great debugging tool since it arrived in with ColdFusion MX (ColdFusion 6). You could display the contents of queries, scopes like CGI, and supporting systems like the operation system and the web server. It is also great for displaying results from CFHTTP, CFERROR and other CF tags that return data.

With the release of ColdFusion 8, CFDUMP gains a number of new features.

  • Format - Output can be HTML as before in a collapsible HTML table or you can output it as plain text much like you see in ColdFusions debugging output.
  • Hide | Show - You can now display partial lists by hiding or showing a limited set of elements
  • Keys- Number of keys in a structure to show.
  • Metainfo - Displays query information including whether it was cached, the execution time, and the SQL script used.
  • Output - Allows you to display to a console (JRun console) or write to a log file or display to the browser as in the past.
  • showUDFs - Lists available user defined functions.
  • Top - Number of rows to show so you can show only a few rows of a query or array.
To use CFDUMP just include the following code in your page and adjust parameters. The only required parameter is var which can be a query, a scope, or any other object. Wrap in pound signs.

<cfdump
var = "#variable#"
expand = "yes|no"
format = "text|html"
hide = "columns|keys"
keys = "number of keys to display for structures"
label = "text"
metainfo = yes|no"
output = "browser|console|file"
show = "columns|keys"
showUDFs = "yes|no"
top = "number of rows|number of levels">

Custom Tags

ColdFusion custom tags are ColdFusion templates just like any other CFML file but are designed to be reused. Coders can save much time by packaging code that is used frequently or can easily add functionality by using free or inexpensive custom tags. There are two general categories of custom tags, one uses only ColdFusion's CFML code. The other packages C++, Java, or other languages into a custom tag that is used by ColdFusion. We'll cover only CFML based tags in this article. For our discussion we will be using CF_States from AspiringGeek.com.

Simple Custom Tags
A simple custom tag is one that is used in a page and adds code to that template without using any inputs. To add a custom tag's functionality to your page, you will place the custom tag in the custom tag directory or in the same folder as the page that you call the custom tag in from. For version control (managing updates to the custom tag) it is best to place the custom tag in the custom tags folder which is assigned through the ColdFusion Administration panel. If you are in a shared hosting environment, you may have to place in each folder where the tag is used.

After the tag is located on the server, you can use it by simply adding a single tag to your template. In the case of CF_States , the file name is states.cfm so we add cf_ to the start of the file name and drop the .cfm extension place the result within mark up brackets: <cf_states>. In your sample you should see a drop down select box listing all US states with California selected.

Custom Tags with Attributes
The previous example saves over 70 lines of code but it may not produce a select box to you or your clients taste. Custom tags can have attributes. Attributes are passed to the custom tag and are used within the custom tag to vary the tag's output. In the CF_States example, we can change what state is pre-selected and also abbreviate the state name to two letters. The attributes for CF_States are NONVERBOSE and SELECTED. By including these attributes, you can control the look of the select box. To show only two letters with Virginia selected use:

<cf_states nonverbose="yes" selected="va">

Creating Custom Tags
Creating a simple custom tag requires saving a portion of code as a ColdFusion template. Creating a custom tag that use attributes, only requires that you reference the attributes using the attributes scope. Within CF_States, attributes.nonverbose and attributes.selected are used to reference the nonverbose and selected attributes that are passed into the custom tag.

Sources for Custom Tags
A great way to learn about ColdFusion code and custom tags is to download sample tags and review the way they are coded. Free and inexpensive custom tags and applications can be found at the following sites:

Various Ways to Include CF Code
There are several ways to include ColdFusion code. Two ways were addressed above, they are summarized below with two other methods.

Ways of Including CF Code
Type Syntax Consideration
Custom

Tag

<CF_filename> This is the simplest syntax for calling in a custom tag. The syntax is adding CF_ to the start of the file name and dropping the .cfm.
Custom
Tag
<CF_filename
ATTRIBUTE-name ="attribute value">
Same as simple custom tags but includes attribute/value pairs.
CFINCLUDE <CFINCLUDE

TEMPLATE="templatename"
>

CFINCLUDE places the content of one template into another as a simple way to include code.
CFMODULE <CFMODULE

NAME="path"
TEMPLATE="path"
ATTRIBUTE ="attribute value"
ATTRIBUTESCOLLECTION="" >

CFMODULE is an alternative way to call a custom tag. It is required when calling a custom tag from within a sub-directory of the custom tag directory. Either Name or Template is used and attributes can be called in indivdually or as a collection from a structure.

Summary
Custom tags provide a great way to use your code or code from others. Custom tags simplifies coding while improving quality by using tested code. The use of attributes adds flexibility while maintaining reusibility. ColdFusions server's central location for custom tags promotes version control.

CFPARAM and How to Uncheck a Checkbox

For anyone new to application development, you may be perplexed when you create your form for editing some data that should allow a user to uncheck a checkbox and update a record to a status of not checked. You will sooner or later discover an oddity about HTML forms. HTML forms won't allow you to uncheck like you think you should be able to. If you uncheck the checkbox, the value becomes NULL and the form doesn't bother to pass the field. You will find that ColdFusion does have a simple solution and much more with the CFPARAM tag.

CFPARAM primary function is to provide a default value if one isn't provided from a requesting form, a URL, or from some other expected variable like a session ID. It also provides a nice way to check the passed values datatype which comes in handy when you need to assure that a numeric value, date or other datatype is passed.

Setting Defaults without CFPARAM
You can set a default without using CFPARAM by using something like:

<CFIF NOT IsDefined("MyVar")
<cfset myvar="">
</cfif>

This sets a MyVar to have a NULL value. It now exists and has a NULL value.

Checking Datatypes without CFPARAM

Checking the data before passing it into a template is often prefered. This can be accomplished with client side validation using JavaScript that you code or that ColdFusion creates with CFFORM and CFINPUT. Alternatively you can use ColdFusion function like isNumeric() in the processing template and handle datatype problems with your own conditional code

Setting Defaults with CFPARAM
To set a default variable with CFPARAM use the following format:

<CFPARAM NAME="MyVar" DEFAULT="">

If MyVar is not passed to the page it will be created with this tag. In this case it will exist with a NULL value.

Checking Datatypes with CFPARAM
A secondary function of CFPARAM is datatype checking. This makes checking that the proper data type is passed to the template but it will produce an error if the wrong type is passed. The may be OK for some in-house applications or your own adminstration areas but for a public site, client side checking with CFFORM, CFINPUT and Javascript is a better pracice.

Datatypes that can be checked with CFPARAM

  • any
  • array
  • binary
  • boolean
  • date
  • numeric
  • query
  • string
  • struct
  • UUID
  • variablename

Summary

CFPARAM is a great tool in setting defaults and dealing with form fields that are passed with no value. It also helps in maintaining your data integrity by checking datatypes

CFTIME: How to Make Content Appear and Disappear

Content on the web often has a shelf life. You may have information that you want up after a certain point in time or you may want it to be gone after a certain time.You may want to have it appear and disappear without having to be editing files or changing out input in some back end system. You will find that you can build a simple system for publishing and removing info with ColdFusion's CFIF tag and CreateDateTime() and Now() functions.

CFIF is one of the most basic and commonly used tags in ColdFusion. We will use it to hide or display content based on comparing a set date to the time that the page is parsed for the visitor.

The CreateDateTime() function takes date and time parameters and creates a ColdFusion date/time object. The format is CreateDateTime(year,month, day, hour, minute, second). An example would be CreateDateTime (2004, 7, 9,19,59, 0) for July 9, 2004 at 7:59pm.

The Now() function takes no parameters and produces a ColdFusion date/time object for the current date and time including seconds.

Example Code

The components are simple so let's put it all together. Our first example is content that displays until a future point in time. In this case if the date/time is less than the target date your content will display. This would be usefull if yo had a contest running and wanted to remove the content from your site when the contest was over.

<cfif #now()# lte #CreateDateTime (2004, 7, 9,19,59, 0)#>
This content is displayed until July 7, 2004 at 7:59pm.

</cfif>

Our next example is content that displays after a future point in time. In this case if the date/time is greater than the target date your content will display. This would be handy if you had an announcement coming up so you could announce it on your web site without having to sit at your computer and trigger the new content.

<cfif #now()# gte #CreateDateTime (2004,7,5,10,30, 0)# >
This content is displayed after July 5, 2004 at 10:30am.
</cfif>

Our last example is content that displays after a future point in time and ends at a later date. In this case if the date/time is greater than the target date and it was smaller than a second target date, your content will display. This would be handy if you had an announcement coming up so you could announce it on your web site without having to sit at your computer and trigger the new content and it would also remove the announcement at the appropriate time.

<cfif #now()# lte #CreateDateTime (2004, 7, 9,19,59, 0)#
AND #now()# gte #CreateDateTime (2004,5, 2,10,30, 0)# >
This content is displayed after May 5, 2004 at 10:30am and disappears after July 7, 2004 at 7:59pm .
</cfif>

Summary

ColdFusion makes dealing with times and dates easy with built in functions like CreateDateTime() and Now(). Developers won't need to be on call for special announcements or the end of a campaign. Test out some examples of your own making and then don't let the clock and your computer dictate when you are making content appear and disappear.

Grouping Results with CFQUERY and CFOUTPUT

Grouping Results

ColdFusion makes it easy to select data out of a database and display it on a page. As soon as you feel good about your success in crossing the divide from static to dynamic, someone will say "That's nice, can you group the list by author?". Whether you are asked to group things by author, make, brand, year or whatever, ColdFusion has you covered with its grouping capabilities.

To present things in groups, we first rely on SQL to group the data before it is presented to ColdFusion. This is done with a GROUP BY or ORDER BY clause.

CLAUSE QUERY
GROUP BYSELECT Author, Title, Publisher
GROUP BY Publisher, Author, Title
ORDER BY SELECT Author, Title, Publisher
ORDER BY Publisher, Author, Title

ColdFusion will then display grouped data by using nested CFOUTPUT tags. In both cases the outter most CFOUTPUT will indicate the QUERY and each CFOUTPUT that is used to group will use a GROUP parameter except the innermost CFOUTPUT. The code below will group authors by publisher and then group books by author.

CODE
<CFOUTPUT Query="myquery" GROUP="Publisher">
  <p>#Publisher#
  <CFOUTPUT GROUP="Author">
    <br>#Author#
    <CFOUTPUT>
   <br>~ #Title#
    </CFOUTPUT>
  </CFOUTPUT>
</p>
</CFOUTPUT>
OUTPUT

Macromedia Press
Forta
~CF WACK Third Edition

~Reality ColdFusion MX

Newbie Press
Barr
~Instant Messenger for Dummies
Gates
~Dominating the World with Software Patches

If you use a GROUP BY clause with a WHERE clause the GROUP BY clause most come after the WHERE clause. Think of this as the SQL engine finding all of the results that match the WHERE statement and then it groups the results.

If you use a GROUP BY clause with an ORDER BY, use the GROUP BY before the ORDER BY clause. The SQL engine will create the groups and then order the groups, this reduces the amount of ordering that is done by SQL since the number of groups is the same or less than the number of members of the groups.

BlogCFC was created by Raymond Camden. This blog is running version 5.8.001.