How To Call A Void ColdFusion Function With No Arguments - coldfusion

I'm writing a ColdFusion function that is the following:
<cffunction name="checkStatusCode" output="false" access="private" returnType="void">
<cfif result.Responseheader.Status_Code eq "400">
<cfset isBadRequest = true>
</cfif>
</cffunction>
It is both void and contains no parameters; I understand how I would call it if it had parameters and returned something; I'd simply put the code in a <cfset> tag. I simply want to run the function. What tags do I need to put it in?

Either this:
<cfset checkStatusCode()>
or, if you are using cfscript,
checkStatusCode();
You could probably use <cfinvoke> if you tried hard enough.

Related

a query string into a structure

I am using taffy and am passing an unknown query string to a function. I do not know the query string values passed in advance, so I am trying to use that in the function but it is not working. Please point me to right direction.
Here is my code:
<cffunction name="qrystringToStruct" returntype="any">
<cfargument name="myStruct" default="#structNew()#" type="struct">
<cfargument name="str" required="true" default="">
<cfscript>
for(i=1; i LTE listLen(arguments.str,'&');i=i+1) {
structInsert(myStruct, i, listGetAt(arguments.str,i,'&'));
}
</cfscript>
<cfreturn myStruct>
</cffunction>
<cffunction name="getCourseById" taffy:verb="get" taffy:docs:hide>
<cfargument name="structurl" type="any" default="" />
<cfdump var="#structurl#">
<cfdump var="#qrystringToStruct(structurl)#" abort>
<cfset var local = {} />
This is how I am calling the url:
http://localhost:9002/taffy/index.cfm//coursesMethods?credits=3&coursetitle=power
but all I am getting is [empty string]
Let me just preface this by saying I've never used Taffy. However with that said, I don't think it's relevant to the problem specified in your posted question. There are a few things in your code that's puzzling to me.
Your call qrystringToStruct(structurl) passes one parameter but your function definition has two parameters.
Why would you declare myStruct as a parameter and then <cfreturn myStruct> in your qrystringToStruct function definition? It makes no sense.
You say you pass the full url to http://localhost:9002/taffy/index.cfm//coursesMethods?credits=3&coursetitle=power? Why not just pass the querystring portion using cgi.QUERY_STRING?
Anyhow, I think you're overcomplicating this and you don't need a custom function to parse out your querystring. All you need is one line of code.
<cfset qryString = listToArray(cgi.QUERY_STRING, "&")>
You can test it out here here.

ColdFusion Application.cfm cfinclude not working

I have a function called "conv" which is needed in several programs within my application. So rather than include it in each program, I put it in the Application.cfm, which looked like this:
<cfapplication name = "Moxware" sessionmanagement = "Yes">
<cfset lang = "LU">
<cfset x127 = Chr(127)>
<cfset mmox = 'Moxware'>
<cfinclude template="conv.cfc">
When I ran one of the programs using the function "conv" (which is in conv.cfc) I got an error that the function conv could not be found.
After I hunted around the internet for ideas I tried this:
<cfapplication name = "Moxware" sessionmanagement = "Yes">
<cfset lang = "LU">
<cfset x127 = Chr(127)>
<cfset mmox = 'Moxware'>
<cffunction name="onRequestStart" output="true" returntype="void">
<cfinclude template="conv.cfc">
</cffunction>
That gave me the same error message as before.
Can someone explain to me how to do this?
Note that the function conv was tested and works just fine.
Instead of using an include, like this...
<cfinclude template="conv.cfc">
Try creating an object, like this...
<cfscript>
MyObject = createObject("component", "conv");
</cfscript>
When you want to access a function within that object, try this...
<cfscript>
SomeValue = MyObject.MyFunction();
</cfscript>
You can include CFM pages into the CFC, but I don't think you can include CFC code into a CFC.
So this is possible...
<cffunction name="OnRequest" access="public" returntype="void" output="true" hint="Fires after pre page processing is complete.">
<cfargument name="TargetPage" type="string" required="true" />
<cfinclude template = "/myMapping/onRequestStart_include.cfm" />
<cfinclude template = "/myMapping/onRequest_include.cfm" />
<cfinclude template = "/myMapping/onRequestEnd_include.cfm" />
</cffunction>
Note the use of a mapping (in our case /myMapping), which can help if your doing this in CFC's. If no mapping is needed, just drop that.
But probably the best option is to instantiate your CFC from within the Application.cfc and use it.
<cfset myConv = createObject("component", "myMapping.conv").init() />
Again using a mapping to get to the CFC. The .init() is not always needed, depends how your CFC is setup.
Then presumably conv has methods you want to use (You talk about it as a single function? A cfc is essentially an object, so you create it as an object first and then use it's methods), so then you'd invoke then by using...
myConv.functionName()
Put another way - Application.cfc is no different from anywhere else in your code. How ever it's invoked and used elsewhere is how you should do it here. The only trick might be pathing to that CFC, which you can do by creating a custom mapping.
Also consider going old school (if it is just a function), and using custom-tags.
Good luck.

Do getter functions need to be used within an ORM component?

Is it essential to use the getter functions when using internal ORM properties within ORM functions? For example in the example below I use #person_id# instead of this.getperson_id().
<cfcomponent persistent="true" table="people" schema="dbo" output="false">
<cfproperty name="person_id" column="person_id" type="numeric" ormtype="int"fieldtype="id"/>
<cffunction name= "hasGifts" returntype="boolean">
<cfset gift_count = ORMExecuteQuery("SELECT COUNT(g.gift_id) FROM gifts g INNER JOIN g.people p WHERE p.person_id = '#person_id#', True )>
<cfif gift_count eq 0>
<cfreturn false>
<cfelse>
<cfreturn true>
</cfif>
</cffunction>
This seems to work fine, but I don't find it documented. It seems like it should be allowed as there is no ambiguity and this is consistent with other languages.
AFAIK it's fine to reference the variables directly as long as they are not lazy loaded. Your ORMExecuteQuery() should use :named or ? position binded value though.

Coldfusion and unscoped variables

I am currently checking all my functions and components for unscoped variables. I am using a tool called varscoper4 to check all functions. Given the following code varscoper tells me that the variable "input" at line 4 in unscoped. Is this true and do i need to scope the argument variable if I alter it?
<cfoutput>#testit(1)#</cfoutput>
<cffunction name="testit">
<cfargument name="input">
<Cfset input = 3>
<cfreturn input>
</cffunction>
FYI if I do not alter the argument variable input in the function varscoper4 does not report any unscoped variables.
<cfoutput>#testit(1)#</cfoutput>
<cffunction name="testit">
<cfargument name="input">
<Cfset var output = 3 + input>
<cfreturn output>
</cffunction>
In your fist code block, input is "unscoped" but CF interprets it as arguments scope. CF will always try to find your unscoped variables by looking through a priority order. You can find more information on that here: http://www.learncfinaweek.com/week1/Scopes/
You can also view for yourself what that looks like by dumping the different scopes and seeing the output.
<cfoutput>#testit(1)#</cfoutput>
<cffunction name="testit">
<cfargument name="input">
<cfset input = 3>
<cfdump var="#variables#" label="variables">
<cfdump var="#arguments#" label="arguments">
<cfdump var="#local#" label="local">
<cfreturn input>
</cffunction>
I would strongly encourage you to take the output of your varscoper tool as a guide to where you should explicitly scope your variables. In that case, your first block of code would look like this. This is for clarity and certainty in your code.
<cfoutput>#testit(1)#</cfoutput>
<cffunction name="testit">
<cfargument name="input">
<cfset arguments.input = 3>
<cfdump var="#variables#" label="variables">
<cfdump var="#arguments#" label="arguments">
<cfdump var="#local#" label="local">
<cfreturn arguments.input>
</cffunction>
Personally, I don't like setting or changing arguments in my functions and methods. I'd rather keep them unadulterated as you have in your second block of code. But even there, I would explicitly scope the arguments so that you know where it came from -- even if not flagged by varscoper
<cfoutput>#testit(1)#</cfoutput>
<cffunction name="testit">
<cfargument name="input">
<cfset var output = 3 + arguments.input>
<cfdump var="#variables#" label="variables">
<cfdump var="#arguments#" label="arguments">
<cfdump var="#local#" label="local">
<cfreturn output>
</cffunction>
Last thing to be added here if it's not clear is that var scoping puts everything int he local scope. You could also do this and it would be functionally equivalent to the previous block of code:
<cfoutput>#testit(1)#</cfoutput>
<cffunction name="testit">
<cfargument name="input">
<cfset local.output = 3 + arguments.input>
<cfdump var="#variables#" label="variables">
<cfdump var="#arguments#" label="arguments">
<cfdump var="#local#" label="local">
<cfreturn local.output>
</cffunction>
You should use arguments.input:
<cfset arguments.input = 3>
Although even better would be to use your second example, with the arguments scope:
<cfset var output = 3 + arguments.input >
Don't modify arguments, leave them as they are when they arrive, incase you want to re-use the original value later on.
http://help.adobe.com/livedocs/coldfusion/8/htmldocs/help.html?content=buildingComponents_29.html

How can I retrieve a (quasi) Array from a URL string?

I would like to achieve something I can easily do in .net.
What I would like to do is pass multiple URL parameters of the same name to build an array of those values.
In other words, I would like to take a URL string like so:
http://www.example.com/Test.cfc?method=myArrayTest&foo=1&foo=2&foo=3
And build an array from the URL parameter "foo".
In .net / C# I can do something like this:
[WebMethod]
myArrayTest(string[] foo)
And that will build a string array from the variable "foo".
What I have done so far is something like this:
<cffunction name="myArrayTest" access="remote" returntype="string">
<cfargument name="foo" type="string" required="yes">
This would output:
1,2,3
I'm not thrilled with that because it's just a comma separated string and I'm afraid that there may be commas passed in the URL (encoded of course) and then if I try to loop over the commas it may be misinterpreted as a separate param.
So, I'm stumped on how to achieve this.
Any ideas??
Thanks in advance!!
Edit: Sergii's method is more versatile. But if you are parsing the current url, and do not need to modify the resulting array, another option is using getPageContext() to extract the parameter from the underlying request. Just be aware of the two quirks noted below.
<!--- note: duplicate forces the map to be case-INsensitive --->
<cfset params = duplicate(getPageContext().getRequest().getParameterMap())>
<cfset quasiArray = []>
<cfif structKeyExists(params, "foo")>
<!--- note: this is not a *true* CF array --->
<!--- you can do most things with it, but you cannot append data to it --->
<cfset quasiArray = params["foo"]>
</cfif>
<cfdump var="#quasiArray#">
Well, if you're OK with parsing the URL, following "raw" method may work for you:
<cffunction name="myArrayTest" access="remote" output="false">
<cfset var local = {} />
<!--- parse raw query --->
<cfset local.args = ListToArray(cgi.QUERY_STRING, "&") />
<!--- grab only foo's values --->
<cfset local.foo = [] />
<cfloop array="#local.args#" index="local.a">
<cfif Left(local.a, 3) EQ "foo">
<cfset ArrayAppend(local.foo, ListLast(local.a, "=")) />
</cfif>
</cfloop>
<cfreturn SerializeJSON(local.foo) />
</cffunction>
I've tested it with this query: ?method=myArrayTest&foo=1&foo=2&foo=3,3, looks to work as expected.
Bonus. Railo's top tip: if you format the query as follows, this array will be created automatically in URL scope ?method=myArrayTest&foo[]=1&foo[]=2&foo[]=3,3.
listToArray( arguments.foo ) should give you what you want.