我正在创建一个API,在每个方法中,我都会调用一个用于审计和故障排除的日志记录方法。类似的东西:
<cffunction name="isUsernameAvailable">
<cfset logAccess(request.userid,"isUsernameAvailable")>
......
</cffunction>
我想避免手动重复方法名称。有没有办法以编程方式确定它?
我查看了GetMetaData(),但它只返回有关组件的信息(包括所有方法),但没有关于当前调用哪种方法的信息。
答案 0 :(得分:11)
现在有三种方式。
如果您使用的是ColdFusion 9.0或更高版本,那么现在有一个名为GetFunctionCalledName()的函数。它会返回你想要的东西。 http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WS7cc222be8a31a47d-6e8b7083122cebfc8f2-8000.html
OR
使用ColdSpring和面向方面编程(http://www.coldspringframework.org/coldspring/examples/quickstart/index.cfm?page=aop)来为您处理此问题。
OR
使用cfthrow生成包含您的信息的堆栈跟踪:
<cffunction name="determineFunction" output="FALSE" access="public" returntype="string" hint="" >
<cfset var functionName ="" />
<cfset var i = 0 />
<cfset var stackTraceArray = "" />
<cftry>
<cfthrow />
<cfcatch type="any">
<cfset stacktraceArray = ListToArray(Replace(cfcatch.stacktrace, "at ", " | ", "All"), "|") />
<!---Rip the right rows out of the stacktrace --->
<cfloop index ="i" to="1" from="#ArrayLen(stackTraceArray)#" step="-1">
<cfif not findNoCase("runFunction", stackTraceArray[i]) or FindNoCase("determineFunction", stackTraceArray[i])>
<cfset arrayDeleteAt(stackTraceArray, i) />
</cfif>
</cfloop>
<!---Whittle down the string to the func name --->
<cfset functionName =GetToken(stacktraceArray[1], 1, ".") />
<cfset functionName =GetToken(functionName, 2, "$")/>
<cfset functionName =ReplaceNoCase(functionName, "func", "", "once")/>
<cfreturn functionName />
</cfcatch>
</cftry></cffunction>
我的建议是使用getFunctionCalledName,或者如果没有使用CF 9 ColdSpring,因为它可能会给你带来一些其他东西。
答案 1 :(得分:4)
我同意t / tpryan。 ColdSpring让这很容易。但是,这是另一种选择。您可以解析CFC文件本身而不是解析堆栈跟踪。
<cffunction name="foo" displayname="foo" hint="this is just a test function" access="public" returntype="string">
<cfset var test = getFunctionName(getMetaData().path, getPageContext().getCurrentLineNo()) />
<cfreturn test />
</cffunction>
<cffunction name="getFunctionName" hint="returns the function name based on the line number" access="public" returntype="string">
<cfargument name="filepath" type="string" required="true" />
<cfargument name="linenum" type="any" required="true" />
<cfset var line = "" />
<cfset var functionName = "" />
<cfset var i = 1 />
<!---- loop over CFC by line ---->
<cfloop file="#ARGUMENTS.filepath#" index="line">
<cfif findNoCase('cffunction', line, 1)>
<cfset functionName = line />
</cfif>
<cfif i EQ ARGUMENTS.linenum><cfbreak /></cfif>
<cfset i++ />
</cfloop>
<!---- parse function name ---->
<cfset functionName = REMatchNoCase("(\bname=[""|'])+[a-z]*[""|']", functionName) />
<cfset functionName = REMatchNoCase("[""']+[a-z]*[""']", functionName[1]) />
<cfset functionName = ReReplaceNoCase(functionName[1], "[""']", "", "all") />
<!---- return success ---->
<cfreturn functionName />
</cffunction>
以上内容是为ColdFusion 8编写的.CFLOOP增加了对逐行循环文件的支持(并且不会将整个文件读入内存)。我做了一些比较堆栈跟踪方法与文件解析的测试。对于直接从单个CFM模板调用的小型CFC,两者都表现良好。显然,如果你有非常大的CFC,解析方法可能会慢一点。另一方面,如果你有一个很大的堆栈跟踪(就像你使用任何流行的框架一样),那么文件解析可能会更快。
- = Viva ColdFusion = -
答案 2 :(得分:1)
你可以试试这个:
<cffunction name="getFunctionName" returntype="any">
<cfset meta =getMetaData(this)>
<cfreturn meta.functions[numberOfFunction].name>
</cffunction>
我尝试了各种各样的东西,但这并不准确,因为函数似乎以反向字母顺序添加到函数数组中。这似乎有限(并没有解决问题)。我想可以调用一些本机java代码,但我需要调查一下。
Re:关于coldspring的另一个答案。我在coldspring的函数元数据上找到了this in depth article。
相关问题:How to get the name of the component that’s extending mine in ColdFusion?
答案 3 :(得分:1)
我想到了另一种可行的方法。
设置OnMissingMethod,如下所示:
<cffunction name="onMissingMethod">
<cfargument name="missingMethodName" type="string">
<cfargument name="missingMethodNameArguments" type="struct">
<cfset var tmpReturn = "">
<cfset var functionToCallName = "Hidden" & Arguments.missingMethodName>
<cfset arguments.missingMethodArguments.calledMethodName = Arguments.missingMethodName>
<cfinvoke method="#functionToCallName#" argumentcollection="#Arguments.missingMethodArguments#" returnvariable="tmpReturn" />
<cfreturn tmpReturn>
</cffunction>
然后使用前缀(在此示例中为“隐藏”)为每个常规方法命名,并将它们标记为私有。所以我最初的例子将成为:
<cffunction name="HiddenisUsernameAvailable" access="private">
<cfset logAccess(request.userid,Arguments.calledMethodName)>
......
</cffunction>
现在所有的调用都会被onMissingMethod截获,它会将方法名称添加到传递给real方法的参数中。
我看到的缺点是内省不再正常,你必须使用命名参数来调用你的所有函数。如果您没有使用命名参数,那么args将随机更改missingMethodNameArguments结构中的顺序。