I saw this code example in a recording and wanted to know what the colon syntax did. I searched the docs, but I wasn't able to find any info on it:
weather.subscribe(observer: application.observers.currentConditions);
I know we can use colon in CF9 for ternary operators:
result = (condition) ? true : false;
But in this case it looks like it's being used to provide named arguments; so what's it doing there?
<cfset result = obj.func(arg:value,thing:42) /> I looked at this and
went blink, blink... That can't be right! You can't use colons for
named arguments! Er, can you? Well, apparently you can.
http://corfield.org/blog/post.cfm/Learn_something_new_every_day_named_arguments
Yes, you are allowed to use both. I think it's a matter of preference. You can even mix.
Try this and see, mocked up some test function:
<cffunction name="testFunction" returntype="void" hint="I just spit out the arguments I get">
<cfdump var="#arguments#" label="arguments">
</cffunction>
<cfset testFunction(arg1:"hello",arg2:"world") />
<cfset testFunction(arg1="hello",arg2="world") />
<cfset testFunction(arg1:"I can mix",arg2="my named argument syntax") />
Personally, I prefer = for named arguments. You might also notice that if you use IntelliJ IDEA for your ColdFusion development that they do not recognize the colon syntax, so for better parsing you would want to use the = syntax. I can't speak for other IDEs
Looks like a typo to me. In ColdFusion you would use an equals sign (=) not a colon to used named arguments.
Your example would become:
weather.subscribe(observer = application.observers.currentConditions);
Related
I wrote the following function:
<cffunction name="check_session_valid" returntype="boolean">
<cfif NOT StructKeyExists(session,"username") OR (len(session.username) EQ 0)>
<script>location.href = 'logout.cfm'</script>
<cfabort>
</cfif>
<cfset session.myApp_start = now()>
<cfreturn true>
</cffunction>
In my .cfm page, I can call that function using
<cfset session_valid = application.lib.check_session_valid()>
OR
#application.lib.check_session_valid()#
What's the difference? Best practice?
Since you asked about best practice, which is a matter of opinion, I think you can improve your function by having it returning either true or false depending on whether or not session.username exists and has a length greater than 0. Then you can use it like this:
<cfif application.lib.check_session_valid()>
code for this condition
<cfelse>
<cflocation href = "logout.cfm">
<!--- note that cfabort is not necessary --->
<cfif>
Regarding your specific question, I think the extra variable, session_valid, is a waste of typing. However, that is simply my opinion.
Not related to your question, I found it curious that you would direct users to a page called logout.cfm. Often users are directed to a page that allows them to log in.
To be honest, both are valid and both would be considered best practice depending on what you are trying to do.
My rule of thumb is if I will need to use the result of a function call more than once, I will set it to a variable
myResult = application.lib.check_session_valid();
If I will only need to use the variable once I would do what Dan mentioned
if( application.lib.check_session_valid() ){
// Do stuff
}
The difference between the examples you showed are
<cfset session_valid = application.lib.check_session_valid()>
This will set the variable named session_valid to whatever is returned from the call to check_session_valid().
#application.lib.check_session_valid()#
This will, in .cfm pages, simply render the value returned from the call to check_session_valid() assuming it is inside of a <cfoutput> tag. There are other places this would also render the value, such as inside a <cfsavecontent>.
So, I ran into an odd bug which I cannot figure out in CF9. It appears to be caused by using a struct literal, inside a function call, inside an if statement, inside a loop. Remove any one of these variables and the condition does not occur.
The following code throws an error:
Error: Variable KEY is undefined.
<cffunction name="test">
<cfreturn true>
</cffunction>
<cfset local.data = { first = "asdf" }>
<cfloop list="first" index="key">
<cfif test({ name = local.data[key] })>
<cfoutput>test</cfoutput>
</cfif>
</cfloop>
Why? If we set the struct to a variable it works. If we do not loop it works just fine as well.
<cffunction name="test">
<cfreturn true>
</cffunction>
<cfset local.data = { first = "asdf" }>
<cfset key = "first">
<cfif test({ name = local.data[key] })>
<cfoutput>test</cfoutput>
</cfif>
Any ideas what is going?
I'll give a better answer once you give a better question ;-) (just tell us the error message as per my comment), but the fact of the matter is that CF's implementation of struct-literal (and array-literal) notation has been blighted by a long list of implementation bugs. I think they have finally been ironed out in CF10.
So, to answer your question slightly obliquely: "what's going on?" Shonky coding in ColdFusion is going on.
What's the fix? When you encounter these problems, use traditional struct notation instead (dot notation or associative array notation).
There's nowt better to do about it other than that, I'm afraid.
Also look in the bug base to see if your particular case has already been logged, and if not: log a new bug.
I need to pass a structure to a method, but it will not always be defined.
Is there something like this that would work?
<cfparam name="system_message" default={}>
When I try this I get, the argument passed to the function is not of type struct.
Also, I realize, I could do this:
<cfif ! isdefined("system_message")>
<cfset system_message = {}>
</cfif>
But I was just wondering if there was a shorter way of doing it, using cfparam.
Thanks for any help!
What about:
<cfparam name="system_message" default="#StructNew()#">
CF8 doesn't like the curly braces version.
You're close. You'll need to write it as:
<cfparam name="system_message" default="#{}#">
If you are passing this to a method, you should consider using <cfargument> within a <cffunction> call rather than the more global <cfparam>. The same "default" attribute applies. Then you know your variable exists only within the ARGUMENT scope within the function, better encapsulation!
<cfargument name="system_message" default="#structNew()#">
Im editing my first ColdFusion script .... I have a form which has <input type="hidden" name="name" value="1">.
On the processing page i want to take that value and set it as a POST variable so i can send it onto another page.
I know how to do it in PHP, like so
$_POST['somename'] = $_POST['name']
How would i do that in CF?
Following the idiom in your php code, you can do something like this:
<cfset form['somename'] = form['name']>
...or, if in cfscript:
form['somename'] = form['name'];
If you're concerned about the existence of the variable, you can precede the assignment with <cfparam>:
<cfparam name="form.name" default=""><!--- assuming blank ok as default --->
<cfset form['somename'] = form['name']>
...or in script:
param name='form.name' default='';
form['somename'] = form['name'];
Of course you can also wrap the assignment in a conditional:
if( structkeyexists(form,'name') ){
form.somename = form.name; // dot notation alternative to bracket syntax
}
This all begs the question of what exactly you're trying to achieve with this approach.
The ColdFusion syntax is similar. "Post" variables are available in the system structure FORM, and "Get" variables in the system structure URL. Like in PHP, values can be accessed using associative array notation. You can also use dot notation (for valid field names)
<cfset otherVariable = FORM["variableName"] >
<cfset otherVariable = FORM.variableName >
i want to take that value and set it
as a POST variable so i can send it
onto another page.
I am not quite sure what you mean there. Typically, you do not need to reassign FORM or URL values. You simply reference the variable in your code.
<cfoutput>
Go To Other Page
</cfoutput>
You can try this by checking if the post variable is set and then storing it with scope of FORM.
<cfif isdefined ("FORM.name")>
<cfset FORM.somename="#FORM.name#">
</cfif>
How Can I get the URL parameter & Value in Coldfusion?
for Ex:-
my URL is
test.cfm?par1=val1&par2=val2&par3=val3
Is it possible to get the second parameter and its value directly?
with <cfset param='#url.par2#'> I can get value of par2,
But my parameters are dynamicically generated from other page and passed to here (par2 may be next time abc2,xyz2 etc..)
So I think better way is to get the parameter and Value in 2nd Possition(Possition dont change always).
Any Idea How can I get it ?
Thanks in advance
You can also access the url scope as a struct, so you could get:
<cfset param2 = url['param2'] />
This is useful if you might have a naming convention for a bunch of fields. Say you're collecting names and emails like so:
email1=foo#bar.com&name1=Fred&email2=xxx#yyy.com&name2=Sally
You could write something like:
<cfloop condition="someCondition">
<cfset email = url['email' & i] />
<cfset name = url['name' & i] />
<!--- Do something --->
<cfset i++ />
</cfloop>
<cfset Param2 = ListGetAt(CGI.QUERY_STRING,2,"&")>
Order of query string variables is not relevant, or your app shouldnt expect it to be relevant. I think your best bet is to have another variable which is a list of the variables in the order. Like so:
test.cfm?par1=val1&par2=val2&par3=val3&list=var1,var2,var3
Notice the presence of the new variable "list".
So you first grab the value of "list" and then takes it 2nd entry "var2" and reference that in the URL scope. You could easily abstract all of this so the names of the variables themselves dont matter. Good error handling will be necessary to guard against missing expectations.
to get the list of params you can use structKeyList(url) or structKeyArray(url) then access those parameters through the url scope like #url['par1']#
<cfset params = structKeyList(url) />
<cfdump label="parameters" var="#params#" />
<cfloop index="ix" list="#params#">
<cfoutput><div>#ix# = #url[ix]#</div></cfoutput>
</cfloop>
as others have mentioned, you really shouldn't rely on the order of parameters
<cfscript>
par2=getToken(cgi.query_string,2,"&"); // contains "par2=val2"
par2name=getToken(par2,1,"="); // contains "par2"
par2value=urlDecode(getToken(par2,2,"=")); // contains "val2"
</cfscript>
You could also use the listGetAt function, which is basically equivalent to getToken, with slightly different syntax.