tags:

views:

308

answers:

6

This has been one of the biggest obstacles in teaching new people ColdFusion.

When to use # is ambiguous at best. Since using them doesn't often create a problem it seems that most people gravitate to using them too much.

So, what are the basic rules?

+3  A: 

The #...# syntax allows you to embed an expression within a string literal. ColdFusion is unfortunately pretty inconsistent about what's a string and what's an expression. Jayson provided a good list of examples of when to use (or not use) #s.

Patrick McElhaney
The tendency to over-use #...# probably results from the fact that many people have difficulty to decide what's an expression and what's a string literal, and that CF is so forgiving about redundant use: <cfset x = #y#> works, and <cfset x = "#y#"> also works, but in both cases ## are redundant.
Tomalak
+6  A: 

Here's what Adobe has to say about it:

Using number signs

Ryan Emerle
+1, but that's a little outdated. For example, it says pound signs can only contain variables or functions or variables. That's no longer true. Any expression (such as #1+1#) works as of CF7 at least.
Patrick McElhaney
Nevermind. I updated the link to the CF8 version of the same document.
Patrick McElhaney
+8  A: 

I think it may be easier to say where NOT to use #. The only place is in cfif statements, and cfset statements where you are not using a variable to build a string in quotes. You would need to use the # sign in almost all other cases.

Example of where you are not going to use it:

<cfset value1 = 5>
<cfset value2 = value1/>

<cfif value1 EQ value2>
    Yay!!!
</cfif>

<cfset value2 = "Four plus one is " & value1/>

Examples of where you will use #:

in a cfset where the variable is surrounded by quotes
<cfset value1 = 5>
<cfset value2 = "Four plus one is #value1#"/>

the bodies of cfoutput, cfmail, and cffunction (output="yes") tags
<cfoutput>#value2#</cfoutput>
<cfmail to="[email protected]" from="[email protected]" subject="x">#value2#</cfmail>
<cffunction name="func" output="yes">#value2#</cffunction>    

in an attribute value of any coldfusion tag
<cfset dsn = "myDB"/>
<cfquery name="qryUsers" datasource="#dsn#">

<cfset value1 = 5>
<cfset value2 = 10/>
<cfloop from="#value1#" to="#value2#" index="i">

<cfqueryparam value="#value1#" cfsqltype="cf_sql_integer"/>

EDIT:

One oddball little thing I just noticed that seems inconsistent is conditional loops allow the variable name to be used with and without # signs.

<cfset value1 = 5>

<cfloop condition = "value1 LTE 10">
    <cfoutput>#value1#</cfoutput><br>
    <cfset value1 += 1>
</cfloop>

<cfset value1 = 5>

<cfloop condition = "#value1# LTE 10">
    <cfoutput>#value1#</cfoutput><br>
    <cfset value1 += 1>
</cfloop>
Jayson
CFLOOP also doesn't need it for the query param whereas CFDUMP does. Not entirely consistent.
Tom Hubbard
CFLOOP expects the /name/ of a query. So if you do use #s in CFLOOP's query attribute, it must evaluate to a string that is a variable name that references a query object.
Patrick McElhaney
+3  A: 

String interpolation:

<cfset name = "Danny" />
<cfset greeting = "Hello, #name#!" />
<!--- greeting is set to: "Hello, Danny!" --->

Auto-escaped string interpolation in cfquery:

<cfset username = "dannyo'doule" ?>
<cfquery ...>
    select u.[ID]
    from [User] u
    where u.[Username] = '#username#'
</cfquery>
<!--- the query is sent to the server (auto-escaped) as: --->
<!--- select u.[ID] from [User] u where u.[Username] = 'dannyo''doule' --->
<!--- note that the single-quote in the username has been escaped --->
<!--- by cfquery before being sent to the database server --->

Passing complex arguments/attributes in CFML:

<cfset p = StructNew() />
<cfset p.firstName = "Danny" />
<cfset p.lastName = "Robinson" />
<cfmodule template="modules/view/person.cfm" person="#p#">
<!--- the variable Attributes.person will be --->
<!--- available in modules/view/person.cfm --->

Passing complex arguments requires # signes only in CFML, not CFScript. In addition, you can pass any kind of value: simple values, arrays, structs, cfcomponents, cffunctions, java objects, com objects, etc.

In all these cases, the text between the # signs does not have to be the name of a variable. In fact, it can by any expression. Of course, for string interpolation, the expression must evaluate to a simple value, but for argument/attribute passing in CFML, the expression may evaluate to any complex value as well.

Justice
+1  A: 

At the risk of sounding like a wise-guy, a rule of thumb is: use # around variables or expressions only when not doing so doesn't yield the correct result. Or: if you don't need them, don't use them.

I like Jayson's answer though.

Dane
A: 

Let's start by assuming you aren't talking about cfoutput tags, cause then the answer is always, elsewhere in your code, if you are inside of quotation marks, then need to use # symbols if it's possible to actually type the value that is going to be used...so if you are in a cfloop tag setting the 'to' attribute, you could easily type 6, but if you want to use a variable you need to use the # symbols. Now if you are in a cfloop tag setting the query parameter, there is no way you could actually type the query into that attribute, there is no way to type a query, so no # symbols are needed.

Likewise in a cfdump tag, you can dump static text, so if you want to dump the contents of a variable, then you will need to use a # symbol. This problem is generally self-correcting, but I feel your pain, your students are probably frustrated that there is no "ALWAYS USE THEM" or "NEVER USE THEM" approach...sadly this isn't the case, the only thing that is true, is only one way inside of quotation marks is going to be correct. So if it isn't working look at it hard and long and think to yourself: "Could I type that value out instead of using the value contained in that variable?" If the answer is no, then the # symbols won't be needed, otherwise get your # character foo on.

np0x