Getting the called function name in CF8
Jan 20 2010
The agency where I work lives on reports and data sets. I have been converting the old reporting system from Microsoft Access to ColdFusion. Every new report meant a new data set.
I wrote a CFC to contain the functions to collect each data set, then a ColdFusion page that would call each function. I needed to know how long each function took to collect the dataset. Each function would record the start and end time when it ran, and then write those times, along with the function called, to a table.
This was a good plan, but the function did not seem to know what its name is. After a few hours of searching discovered that one could get the current line number by using the following.
More searching turned up a page that showed how to the line number each function started on. Knowing that and the current line number would be all you needed to know the function name. The only part I did not like was reading the CFC each time it was called.
A better way might be to read the CFC when the application starts and store the information in memory. Create a function and set an array to hold the data.
2
3<cfset variables.dsn = "">
4<cfset variables.as400 = "#application.dsn.AS400#" />
5<cfset variables.cfMain = "#application.dsn.cfMain#" />
6<cfset variables.functions = "" />
When the application starts initialize the component.
2 <cfargument name="dsn" type="string" required="true">
3
4 <cfset variables.dsn = arguments.dsn />
5 <cfset variables.functions = getFunctionNames( getMetaData().path ) />
6 <cfreturn this>
7</cffunction>
The function, getFunctionNames reads the component and stores the name and the starting and ending line of each function.
2 <cfargument name="filepath" type="string" required="true" />
3
4 <cfset var line = "" />
5 <cfset var functionName = "" />
6 <cfset var i = 1 />
7 <cfset var a = 0 />
8 <cfset var myNames = arrayNew(2) />
9
10 <cfloop file="#arguments.filepath#" index="line">
11 <cfif findNoCase('cffunction', line, 1)>
12 <cfset functionName = REMatchNoCase("(\bname=[""|'])+[a-zA-Z0-9_]*[""|']", line) />
13 <cftry>
14 <cfset functionName = REMatchNoCase("[""']+[a-zA-Z0-9_]*[""']", functionName[1]) />
15 <cfset functionName = ReReplaceNoCase(functionName[1], "[""']", "", "all") />
16 <cfset a++ />
17 <cfset myNames[a][1] = functionName />
18 <cfset myNames[a][2] = i />
19 <cfcatch type="any">
20 <cfset myNames[a][3] = i />
21 </cfcatch>
22 </cftry>
23 </cfif>
24 <cfset i++ />
25 </cfloop>
26 <cfreturn myNames />
27</cffunction>
A cfdump of myNames looks like this. An array with the function name, the line number the function starts on and the line number the function ends on. For the function to get its name, the following line is added to each function.
This calls getFunctionName which loops through variables.functions and returns the name of the called function. It is not the most elegant method but it works well.
2 <cfargument name="linenum" type="any" required="true" />
3
4 <cfset var functionName = "" />
5 <cfset var name = "" />
6
7 <cfloop array="#variables.functions#" index="name">
8 <cfif arguments.linenum GT name[2] AND arguments.linenum LT name[3]>
9 <cfset functionName = name[1] />
10 <cfbreak />
11 </cfif>
12 </cfloop>
13 <cfreturn functionName />
14</cffunction>










#1 by Ben Nadel on 1/23/10 - 6:55 PM
#2 by Gary Funk on 1/23/10 - 7:08 PM
#3 by Ben Nadel on 1/23/10 - 7:12 PM
#4 by Gary Funk on 1/23/10 - 7:20 PM
#5 by Ben Nadel on 1/23/10 - 7:22 PM
#6 by Raymond Camden on 1/24/10 - 6:16 PM
#7 by Gary Funk on 1/24/10 - 6:32 PM