Sending MultiPart Email Messages with ColdFusion

Here is an example of how to send a multipart email message with ColdFusion:

view plain print about
1<cfmail subject="MultiPart Email Test" type="text/html" to="you@test.com" from="someone@test.com">
2 <cfmailpart type="text/plain">
3 Plain text goes here
4 </cfmailpart>
5 <cfmailpart type="text/html">
6 HTML version goes here
7 </cfmailpart>
8</cfmail>

It's important that you put the text-only version of the message FIRST in the mailpart tag list, otherwise GMail will always display the text-only version of the email message and never display the HTML version of the message!

Case sensitive "LIKE" comparison in ColdFusion Query of Queries

I encountered an unexpected behavior while trying to remove all records with hotmail email adresses from a query of some clients.

The query of queries was pretty simple:

view plain print about
1<cfset tmpQry = arguments.qSourceData>
2<cfquery name="returnQueryNoHotmail" dbtype="query">
3    select * from tmpQry
4    where email not like '%@hotmail.com%'
5</cfquery>
6<cfset rtnQuery = returnQueryNoHotmail>

 

The problem that I found was that it was removing SOME of the records with hotmail addresses, but not all. Upon further inspection of the data, I found that the records that were not being matched with this query all had Hotmail addresses in uppercase - for example: JOHN123@HOTMAIL.COM instead of john123@hotmail.com.

So the issue here is that the LIKE condition in a query of a query in ColdFusion 8 is case sensitive.

To fix this, and make sure that I get any other "hotmail.com" record, I used the LOWER() function, which would match either Hotmail.com, HOTMAIL.COM, hotmail.com, hotmail.COM or any other combination of the characters.

view plain print about
1<cfset tmpQry = arguments.qSourceData>
2<cfquery name="returnQueryNoHotmail" dbtype="query">
3    select * from tmpQry
4    where lower(email) not like '%@hotmail.com%'
5</cfquery>
6<cfset rtnQuery = returnQueryNoHotmail>

 

Additionally, you can also use regular expressions for your LIKE comparison. For example, if you want to get all clients whose first name started with the letter "E" through the letter "M", you could write it like this:

view plain print about
1<cfquery name="qOq" dbtype="query">
2    select * from qClients where first_name like '[E-Me-m]%'
3</cfquery>

Pretty cool!

You can see the full reference on query of queries here in the docs (which is where I found the answer):
http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=using_recordsets_7.html

 

Easy way to get the SQL of a query

I can't count the number of times that I have needed to see the actual SQL that was used in a query, since the query is often built dynamically and based on several different conditions that are passed in.

The easy way to do this is to save the query to a result variable and the dump the sql of the result variable.

Example:

view plain print about
1<cfquery name="myQuery" datasource="#dsn#" result="myQueryResult">
2&nbsp;&nbsp;&nbsp;select client_id, first_name, last_name, email from clients
3&nbsp;&nbsp;&nbsp;where
4&nbsp;&nbsp;&nbsp;<cfif bSubscribed eq 1>
5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;email_authorized = 1
6&nbsp;&nbsp;&nbsp;<cfelse>
7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;email_authorized = 0
8&nbsp;&nbsp;&nbsp;</cfif>
9</cfquery>
10
11<!--- dump the sql that was used for the query --->
12<cfoutput>#myQueryResult.sql#</cfoutput>

That's it!

CFMenu - Easy as Pie

I have to say that I love the new <cfmenu> tag in ColdFusion 8. I found it to be the perfect solution for an intranet menu that has grown and grown and grown over time to be a huge list of text links - a list that was unreadable to me, even though I used the menu all the time every day. It got to the point that I literally had to stop for a few seconds to find a link that I used on a very regular basis because it was so buried in text.

Not very user-friendly!

[More]

Getting the data type of a ColdFusion query column

I was looking for a way to get the data type of a query column so that I could apply different logic based on the type. I found the solution for this on another blog: http://www.bennadel.com/blog/308-Ask-Ben-Finding-The-SQL-Data-Type-Of-A-ColdFusion-Query-Column.htm

Using the GetMetaData() function, you can pass in a query object and return an array of structures that contains each column in the query and information about that column. Very useful!!

Basically, to use the function, you just pass in the query name:

view plain print about
1<cfset arrMetaData = GetMetaData(myQuery)>

I have expanded on the original blog entry a little bit by creating a function that I placed in my generic Utilities component to be used throughout the application.

[More]

Use AttributeCollection for Custom Tags to Reduce Coding and Errors

I've recently started using the attributeCollection attribute for passing attributes to a custom tag instead of the name=value approach. I've found that this approach is much easier to read, to change and is less error prone, especially when your code will require you to use different custom tags with that use the same attributes, depending on the if statement match.

[More]

Page Numbers in clickable boxes are easier to use

I have to say that I really like the usability of page numbers (or alpha lists) in clickable boxes. They are much easier to use/select than just the one-character links, which are often teeny tiny and too close together. So here is an example of how to clickable boxes with CSS - you just have to define the style, then wrap all the links in a div with the "pagination" class. 

Example CSS: 

view plain print about
1/* ------------------------------------------------------- */
2div.pagination {padding:3px; margin:3px; text-align:left; font-size:11px; font-family: Arial, Verdana, Helvetica, sans-serif;}
3
4div.pagination a, div.pagination a:visited {padding: 2px 5px 2px 5px; margin-right: 2px; background: transparent; border: 1px solid #cccccc; text-decoration: none; color: #004499;}
5
6div.pagination a:hover, div.pagination a:active { border: 1px solid #cccccc; color: #000000; background-color: #dddddd;}
7
8div.pagination span.current a:link, div.pagination span.current a:visted { color: #004499; padding: 2px 5px 2px 5px; margin-right: 4px; font-weight: bold; border: 1px solid #e0d9b8; background-color: #edeadb;}
9
10div.pagination span.disabled {padding: 2px 5px 2px 5px; margin-right: 2px; border: 1px solid #e0d9b8; color: #004499; background-color: transparent;}
11/* ------------------------------------------------------- */

Example HTML/ColdFusion code:

view plain print about
1<cfoutput>
2 <div class="pagination">
3 Port Index:&nbsp;&nbsp;
4 <cfloop list="#alphaList#" index="thisAlpha">
5 <cfif alpha neq thisAlpha>
6 <a href="#cgi.SCRIPT_NAME#?#cgi.QUERY_STRING#&alpha=#thisAlpha#">#thisAlpha#</a>
7 <cfelse>
8 <span class="current"><a href="#cgi.SCRIPT_NAME#?#cgi.QUERY_STRING#&alpha=#thisAlpha#">#thisAlpha#</a></span>
9 </cfif>
10 </cfloop>
11 </div>
12</cfoutput>

Faster form fields to function

Here's an easier way to pass in the values of a form submission to a function. Instead of defining each form field as an argument to be passed into the function, you can use the form structure as the argument itself.

Example Old Code:

view plain print about
1<cfscript>
2 this.myFunction(first_name='#form.first_name#', last_name='#form.last_name#', phone='#form.phone#');
3
</cfscript>
4
5<cffunction name="myFunction">
6
7<cfargument name="first_name" type="string" required="no" default="">
8<cfargument name="last_name" type="string" required="no" default="">
9<cfargument name="phone" type="string" required="no" default="">
10
11<cfquery datasource="myDSN">
12 insert into customers (first_name, last_name, phone)
13 values ('#arguments.first_name#', '#arguments.last_name#', '#arguments.phone#')
14</cfquery>
15
16<cfreturn>
17</cffunction>


Example New Code with form passed as a structure to the function:

view plain print about
1<cfscript>
2 this.myFunction(form);
3
</cfscript>
4
5<cffunction name="myFunction">
6<cfargument name="myForm" type="struct" >
7
8<cfquery datasource="myDSN">
9 insert into customers (first_name, last_name, phone)
10 values ('#arguments.myForm.first_name#', '#arguments.myForm.last_name#', '#arguments.myForm.phone#')
11</cfquery>
12
13<cfreturn>
14</cffunction>


That's it - less typing, less room for error, and when you add/change a form field, you only have to change it in the form and in the function itself!

Cindi V.