| [<--Prev] [Next-->] | ||
| [Printable Version] [Search: ] [Daryl's TCP/IP Primer] [Daryl's ColdFusion Blog] |
![]() |
A variable is a named location in memory that holds a value. The "type" of variable refers to the type of data stored at that memory location. Some languages strongly resist converting numbers to strings (text) values and vice-versa; these languages are referred to as "strongly typed." ColdFusion is a "loosely typed" programming language. This means that variables are not (generally speaking) strongly associated with one data type or another; for example, a variable assigned a numeric value can be used as if it were a string variable. The length of text variables need not be defined before use, and I've created string variables several megabytes in length. The basic data types in ColdFusion (not that it's really all that important) are Numeric, String, Date/Time, and Boolean.
There are others data types: arrays can be created; SQL queries, once executed, become a type of array; and structures were added in version 4.0. A List is almost another data type is ColdFusion, but it is actually just a string with some sort of delimiter, usually a comma. Special variables cannot be automatically converted to other types.
A string can only be converted to a numeric if it looks like a number. "45.3" can be converted; "two" cannot be converted. Any number can be converted to a string. The two basic Boolean values are TRUE and FALSE; however YES and NO work well too. Non-zero numbers are considered TRUE; zero is considered FALSE. String values other than true, false, yes, no, or something easily converted to numeric, will cause an error to be displayed.
Variables names are NOT case-sensitive, must start with a letter, and can include letters, numbers, and underscores ("_"). "Customer_Name" is valid; "2Customer" and "Customer Name" are not valid variable names. The value of a variable is displayed by expressing the variable in pound signs, within a CFOUTPUT block:
<CFOUTPUT>Welcome to our online system, #Customer_Name#!</CFOUTPUT>
All variable names that contain a single value exist in "variable scopes." (More about that in the next section.)
SQL (as implemented by ODBC) has three data types: string, numeric, and date/time (or timestamp.) SQL queries are sent to SQL-based databases via the <CFQUERY> tag.
| * |
There is no such thing as a SQL database. SQL is a query syntax, and has rules about table structure and system tables, but SQL has no provisions for how data is stored. Therefore, database systems can be said to be SQL compliant databases, and SQL may be the only means by which to manage the database, but there is no such thing as an SQL database. |
SQL strings begin and end with a single quote ('). If you want to embed a single quote in a query, you need to type two single quotes. (Programmers generically called this 'escaping' a reserved character.) Therefore, to express the value:
I don't get this.
as an SQL string, you would type:
'I don''t get this.'
Within a CFQUERY, ColdFusion will replace single quotes in #variables# with double quotes automagically; however, ColdFusion will not do single quote escaping for functions. Therefore, any data that may contain single quotes should be manipulated outside of the CFQUERY statement.
|
Wrong: |
<CFQUERY...>
SELECT * FROM Users
WHERE UserName = '#ucase(User_Name)#'
</CFQUERY>
|
|
Right: |
<CFSET UserName = ucase(UserName)>
<CFQUERY...>
SELECT * FROM Users
WHERE UserName = '#User_Name#'
</CFQUERY>
|
Numbers are provided to SQL without any special consideration. However, ColdFusion programmers must be sure to handle numeric values passed into queries! Otherwise, the supposedly numeric value could be 'hijacked' by a malicious user and used to run other SQL commands. Say a link is created that passes a numeric row identifier "OrderID." OrderID is the primary key for the table "Orders" and is numeric. Although it's tempting to write a query to get the order from the database like this:
SELECT * FROM Orders WHERE OrderID = #OrderID#
Someone could easily replace the numeric OrderID (e.g. "5") an the URL line (or alter the form, etc.) with a value followed by a malicious command, such as "http://myserver/MyPage.cfm?OrderID=5+delete+from+orders". The SQL passed to the database system would then look like this:
SELECT * FROM Orders WHERE OrderID = 5 delete from orders
Most high-end database systems allow more than one SQL statement per query. Without very conservative database security settings, the above command would delete all orders from the system. You don't want to get that phone call. All numeric values passed by the user should be wrapped by the ColdFusion val() function, which returns the numeric value of the parameter supplied to it, or zero (0) if the value is not numeric. Therefore, val("5") is 5, but val("5 delete from orders") is 0. The code would be properly rewritten like this:
SELECT * FROM Orders WHERE OrderID = #val(OrderID)#
ODBC was designed to provide one consistent application interface to many different DataBase Management Systems (DBMSes). There is a problem with providing one SQL front end to many DBMS back end systems...
| * |
There is no such thing as a standard format for date and time values in SQL. Therefore, expressing date and time values has traditionally been DBMS implementation-specific. To provide consistency, the designers of ODBC developed a standard format for SQL dates and times, which is translated to the DBMS native format by its ODBC driver. |
Date/Time values, in ODBC, are provided in one of the following three formats:
For time (and timestamp) values, the seconds and fractional seconds portion are optional. Many SQL systems do not support fractional second timestamps; if you attempt to use a fractional second value with these systems, strange errors may occur.
An example SQL Insert showing all three data types:
<CFQUERY Name="InsertCustomer" DataSource="CustomerData">
INSERT INTO Customers (
CustomerName
,CustomerAge
,DateAdded
) VALUES (
'John''s Bakery'
,30
,{ts '1999-11-01 15:54:00'}
)
</CFQUERY>
ColdFusion organizes variables into "variable scopes." A variable scope can be thought of as a container for variables. When you assign a value to a name without specifying a scope, you are actually modifying (or creating) a variable in the "Variables." scope. The following statements are synonymous:
<CFSET MyVariable = 1> <CFSET Variables.MyVariable = 1>
The most commonly used variable scopes are (in order of precedence):
|
[QueryName]. |
When you create a query using <CFQUERY>, you create a new variable scope with the name specified with the Name attribute of <CFQUERY>. If you use <CFLOOP> or <CFOUTPUT> to loop around the result set of a query, the "current row" of that query becomes the highest-precedence variable scope. |
|
Variables. |
Programmer-defined variables (<CFSET>) |
|
CGI. |
The Web server's "environment" variables. I commonly use CGI.REMOTE_ADDR (the IP address of the user), CGI.SCRIPT_NAME (the name of the currently running script, from the browser's perspective), and CGI.HTTP_USER_AGENT (the type of browser requesting the page, according to the browser. Useful for creating Netscape/IE versions of JavaScript) |
|
File. |
Variables created with <CFFILE> |
|
URL. |
Variables passed by HREF or FORM Method="Get" |
|
Form. |
Variables passed by FORM Method="POST" |
|
Cookie. |
Cookies you've set with <CFCOOKIE> |
| Client. |
Variables created using Client State Management |
If you don't explicitly name the scope for the variable you are using, ColdFusion automatically searches through the above scopes, in the order listed.
| * |
Be sure you explicitly scope variables used within query loops that have the same name as a column in the query. Otherwise, you may use the value from the query instead of the value from the variable. |
HTML comments are delimited by <!-- and -->. HTML comments are sent to the browser, and can be viewed by anyone who chooses "View Source" in their browser:
<!-- This is an HTML comment -->
ColdFusion comments have three (or more) hyphens on each end, and can be nested:
<!--- This is a ColdFusion Comment <!--- and so is this ---> this is still part of the first CF comment end of comment --->
ColdFusion comments are source-only; they are not sent to the browser. Nesting of ColdFusion comments can be very confusing for programmers and is not recommended. Any tags or functions found inside ColdFusion comments are not executed; however, ColdFusion code found inside HTML comments is executed. I will occasionally use HTML comments to produce debugging information that is only viewable when I select "View Source" in my browser.
| * |
I suppose it's theoretically possible to over-comment code, but I've never seen anyone do it. |
Perhaps the core ColdFusion tag, CFOUTPUT lets you actually change the document from static HTML to a page that produces dynamic output:
<HTML> <BODY> <CFOUTPUT>Your IP address appears to be #CGI.Remote_Addr#</CFOUTPUT> </BODY> </HTML>
Output:
Your IP address appears to be 10.1.5.17
In a nutshell [is using that cliché a copyright infringement?], the <CFOUTPUT> tag tells ColdFusion to start examining the template for pound signs ('#'). ColdFusion variable names or expressions are expected to be found within pound signs. If you actually want to produce a pound sign, you must double it. Doubling the pound signs is known as "escaping" them, a generic term used to indicate that certain special characters are to be ignored. The term originates from early UNIX terminals, which used the ASCII ESC character (yes, just like the one on your keyboard) to indicate the start of commands intended for the terminal (e.g., to change text color or position.) Therefore, HTML hex color commands need to have the pound signs doubled, or ColdFusion will generate an ugly error.
| Wrong: |
<HTML> <BODY> <CFOUTPUT> <CFSET SalePrice = "19.95"> <CFSET SalesTax = "0.065"> <FONT Color="#ccffCC"> The price with tax is #val(round((SalePrice*(1+SalesTax))/100 )*100)# </FONT> </CFOUTPUT> </BODY> </HTML> |
| Right: |
<HTML> <BODY> <CFOUTPUT> <CFSET SalePrice = "19.95"> <CFSET SalesTax = "0.065"> <FONT Color="##ccffCC"> The price with tax is #val(round((SalePrice*(1+SalesTax))/100 )*100)# </FONT> </CFOUTPUT> </BODY> </HTML> |
Notice the use of the val() and round() functions. Complex calculations can be performed using ColdFusion functions in <CFOUTPUT> sections.
The greatest power of ColdFusion lies in the ability for ColdFusion to take user input and perform dynamic database queries based on that input. Let's start with the basics:
So, let's create a basic form to ask for a name and birth date, then display their age and the day of their next birthday. The first page template we'll write will be called "Birthday1.cfm" and the second will be called "Birthday2.cfm":
| Birthday1.cfm |
|---|
<HTML> <BODY> <FORM Action="Birthday2.cfm"> Please enter your name: <INPUT Type="Text" Name="ffName" Size=50><br> Please enter your birth date (m/d/yyyy): <INPUT Type="Text" Name="ffBirthdate" Size=12><br> <INPUT Type="Submit" Value="Show Next Birthday"> </FORM> </BODY> </HTML> |
| Birthday2.cfm |
<HTML>
<BODY>
<CFPARAM Name="ffName" Default="Hey You">
<CFPARAM Name="ffBirthdate" Default="">
<CFOUTPUT>
<CFIF IsDate(ffBirthdate)>
You were born on #DateFormat(ffBirthdate,"dddd, m/d/yyyy")#<br>
<!--- find birthday for this year --->
<CFSET NextBirthday=CreateDate(year(now()),month(ffBirthdate),day(ffBirthdate))>
<CFIF DateCompare(now(), NextBirthday) IS 1>
<!--- this year's birthday already passed; add a year --->
<CFSET NextBirthday = DateAdd("y",1,NextBirthday)>
</CFIF>
Your next birthday is #DateFormat(NextBirthday,"dddd, m/d/yyyy")#<br>
You are #DateDiff("yyyy",now(),ffBirthDate)# years old.
<CFELSE>
I'm sorry, I don't recognize '<b>#ffBirthdate#</b>' as a date.
</CFIF>
</CFOUTPUT>
</BODY>
</HTML>
|
Note the use of the <CFIF> tag to first determine if the date entered by the user is recognizable by ColdFusion; then <CFIF> is used to determine if the user's birthday for this year has already passed. There are also numerous ColdFusion functions used in this block of code; I strongly encourage you to read and understand the manual sections for those functions, since they are some of the most used (and most powerful) functions of ColdFusion. I will not take the time to explain most of the ColdFusion functions used in this document.
| * |
I strongly recommend reading the reference manual cover to cover! Many of the tags and functions will not "click" the first time through. Or, to a lesser extent, the second time through. However, you will vaguely remember what functions and tags are available. The next time you see a problem easily solved by a certain tag or function, even if you don't remember the name of the tag or function offhand, you will remember that there is an easy way to accomplish the task at hand. No one expects you to memorize the manual; however, general knowledge of what capabilities are available through ColdFusion is a must for every professional programmer. |