Link to home
Start Free TrialLog in
Avatar of jasch2244
jasch2244

asked on

Cfparam Question

I'm confused as to how to properly use the cfparam tag in coldfusion. What I'm trying to do is to set a variable that if not contained in the URL to set a default value for the variable.

Can someone please explain how to properly use this tag and logic behind it?

See code: I would like to rid myself of the #URL.cDate# and just have cDate as the variable name. I know I named it that but again if it is not in the URL and you are "pre setting the variable" how do you referr to it? Confusing :(
<cfparam name="URL.cDate" default='year(Now())'>

<cfquery datasource="#application.datasource#" name="Closings"> 
SELECT
closings.Status,
closings.ClosingID,
closings.ClosingDate,
closings.Address,
closings.SoldPrice,
closings.response,
closingstatus.statusID,
closingstatus.StatusDesc
FROM
closings ,
closingstatus
WHERE
closings.Status =  closingstatus.statusID AND
closings.Status =  2 AND 
year(closings.ClosingDate) = #URL.cDate#
ORDER BY
closings.ClosingDate ASC
</cfquery>

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of hefterr
hefterr
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
<cfparam name="URL.cDate" default='year(Now())'>
cfparam is used to set the default value of a varible but only if it is not already defined.
try
<cfparam name="URL.cDate" default="#year(Now())#"> which should work but if it doent use this

<cfif isdefined("url.cdate") and #url.cdate# is not "">
<cfelse>
<cfset url.date="#year(Now())#">
</cfif>

SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
CFPARAM - Tests for the existence of a parameter (that is, a variable), validates its data, and, if a default value is not assigned, optionally provides one

<cfparam name="URL.cDate" default="">

<cfif URL.cDate NEQ ''>
      <cfset cDateVar = URL.cDate />
<cfelse>
      <cfset cDateVar = year(now()) />
</cfif>

And you can use cDateVar in your query instead of url.cDate.

jasch2244,
Thanks for the points.

One last followup.  You seemed to initially be put off about using a URL variable that you yourself created (was not created / passed by CF).  This is OK to do as "URL" is an exisiting  "collection" available for your program (take a look a "collections" in the CF docs).  You could simarly create a FORM.myvariable if you felt the need in an "action" program that processed the results of a form if the the form variable was not passed (eg radio button not selected).

regards,
hefterr
Avatar of _agx_
See code: I would like to rid myself of the #URL.cDate# and just have cDate as the variable name.

Why?

It's actually *better* to use the variable's scope ie URL.variableName.  The same variable name can exist in multiple scopes.  So if you don't scope your variables, CF has to work that much harder to figure out what you mean by #cDate#.  Plus, CF might even find the wrong value.  For example if you had 3 variables all named "cDate", how would CF know which one you wanted?

       url.cDate = 2010
       form.cDate = 2008
       variables.cDate = 10/01/2011


So I guess I'm wondering why you're trying to avoid good coding practices.. :)
Hi _agx_,
You are correct (as usual).  I was just trying to answer the theoretical side of the question.  I thought the original code was fine (as I had indicated in my original post).

FYI.  I looked up the precedence that Coldfusioon uses for Scope :)
It would be :
  closings.cDate = 2008  (Query Scope)
  variables.cDate = 10/01/2011
  url.cDate = 2010
  form.cDate = 2008

followed by :
  cookie.cDate = 2008
  client.cDate = 2008


hefterr
 


I was just trying to answer the theoretical side of the question

Yeah, that's what I figured :) I was just trying to get at the real reason behind the question.  Because usually this isn't something you *want* to do ...

The only time I've ever done it deliberately was working with an old spaghetti code app.  Unfortunately nothing was scoped and the same name variables were all over the place.  They also liked to duplicate variables unnecessarily, which drove me crazy!  Totally obfuscated already bad code, making it impossible to follow.  What a nightmare! (Can you tell I'm scarred... ;-)
The only time I've ever done it deliberately was working with an old spaghetti code app.

Hey, where did you get my code from :)
Haha =)
Avatar of jasch2244
jasch2244

ASKER

Hey all! I thought through my usual igornance that if you used url variables that there could be sql injection as a result of passing variables through the URL's am I crazy for thinking this way? I'm not a full time coder as I dabble when I can :)
Nope. You're not crazy.  Any time user supplied values are used in a query (URL, FORM, etc..) there's a possibility for sql injection.  The main defense against that is to always use cfqueryparam.  It ensures the supplied values won't be executed.

...
WHERE
closings.Status =  closingstatus.statusID AND
closings.Status =  2 AND 
year(closings.ClosingDate) = <cfqueryparam value="#URL.cDate#" cfsqltype="cf_sql_integer">

Open in new window


Btw: Omitting the scope or copying the value into another variable does nothing to remove the risk. It's still there. That's why always using cfqueryparam a good habit to get into.
jasch2244,
FYI.  agx the is ColdFusion guru of gurus!!
Hi agx,

===>Plus, CF might even find the wrong value.  For example if you had 3 variables all named "cDate", how would CF know which one you wanted?

I know we're off point here.  But could you give an example where you might get the wrong value by not scoping your variables.

When I tried your example above and just used #Cdate# I either got the value I set it to or variable cDate note defined.  I didn't get a different scopped value?

I can set this up as a question for points if you want?

hefterr
Hi hefterr,

I just mean that whenever you omit the scope, you're basically leaving everything up to CF.  It's like saying "use the 1st variable by that name that you find. I don't care which one".  Many times it works out correctly.  But there's no point leaving it up to chance.

Here's one example I ran across.  Take a simple query with a column value of 50
<cfset qry = queryNew("")>
<cfset queryAddColumn(qry, "Total", listToArray("50"))>

Inside the output loop, add 100 to the value and display the total.  You might expect the value displayed to be 150. Because of scoping, it's not. The value displayed is 50

<cfoutput query="qry">
      <cfset total = total + 100>
      <!--- What value would you expect to see here? --->
      <strong>total=</strong> #total#
</cfoutput>
When I tried your example above and just used #Cdate# I either got the value I set it to or variable cDate note defined.  I didn't get a different scopped value?


I may have misunderstood your question.  To clarify, I wasn't talking about cfparam specifically. Just scoping in general.   Say "cDate" existed in the url and variables scope

     <cfparam name="url.cDate" default="I'm a URL variable">
     <cfset cDate = "I'm from the VARIABLES scope">

If you output #cDate#, without scoping, CF would pick up the value in the variables scope. But you might have wanted/expected the url scoped value instead.  
    <cfoutput>cDate = #cDate#</cfoutput>

So without scoping, it's possible to create subtle bugs/issues unintentionally.  

aqx,
I wasn't talking about cfparam either - but scoping.  OK, It's a good practice.  I beleive CF assumes an unqualified variable name to be variable.something.  I must admit that I do not add "variable." infront of all my local variable (as it takes a lot of typing!).  I scope all others as you  somewhat have to.

OK.  Thanks for the clarification.  I think we're on the same page.
Give yourself a few more "beer points" on me :)

hefterr

I beleive CF assumes an unqualified variable name to be variable.something

Yep, though the scope name is plural ie variables.something.  

I scope all others as you  somewhat have to.

Well technically you don't have to most of the time.  So I think you've honed in on the real point. For most variables, CF lets you get away with just using:

     <cfset url.cDate = "something">
     <cfoutput>#cDate#</cfoutput>

But like we agreed, that's terribly ambiguous and subject to scoping problems.  So it's better to always provide the variable scope.  At the very least, scope everything that *isn't* a local variable. You can still run into problems, like the query example above, but at least you've reduced the likelihood.

I must admit that I do not add "variable." infront of all my local variable
Personally, I like it.  Especially when working with  cfc's and functions. But I know a lot of people find it too "wordy" so I usually omit it in code snippets :)