¿Puede un método ColdFusion cfc determinar su propio nombre?
(4)
Estoy de acuerdo con tpryan. ColdSpring hace esto muy fácil. Sin embargo, aquí hay otra alternativa. En lugar de analizar el seguimiento de la pila, puede analizar el archivo 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>
Lo anterior está escrito para ColdFusion 8. CFLOOP agregó soporte para el bucle sobre archivos línea por línea (y no lee todo el archivo en la memoria). Hice algunas pruebas comparando el método de rastreo de pila con el análisis de archivos. Ambos funcionaron igual de bien en un CFC pequeño que se llama directamente desde una única plantilla de CFM. Obviamente, si tiene CFC muy grandes, el método de análisis podría ser un poco más lento. Por otro lado, si tiene un rastro de pila grande (como si está utilizando cualquiera de los marcos populares) entonces el análisis de archivos puede ser más rápido.
- = Viva ColdFusion = -
Estoy creando una API, y dentro de cada método llamo a un método de registro para auditar y solucionar problemas. Algo como:
<cffunction name="isUsernameAvailable">
<cfset logAccess(request.userid,"isUsernameAvailable")>
......
</cffunction>
Me gustaría evitar repetir manualmente el nombre del método. ¿Hay alguna manera de determinarlo programáticamente?
Miré GetMetaData () pero solo devuelve información sobre el componente (incluidos todos los métodos), pero no se menciona qué método se está llamando actualmente.
Pensé en otra manera que podría funcionar.
Configura un OnMissingMethod algo como esto:
<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>
A continuación, nombre cada uno de los métodos habituales con un prefijo ("Oculto" en este ejemplo) y márquelos como privados. Entonces mi ejemplo inicial sería:
<cffunction name="HiddenisUsernameAvailable" access="private">
<cfset logAccess(request.userid,Arguments.calledMethodName)>
......
</cffunction>
Ahora todas las llamadas serán interceptadas por onMissingMethod, que agregará el nombre del método a los argumentos que pasan al método real.
Las desventajas que veo a esto son que la introspección ya no funciona correctamente, y debes usar argumentos con nombre para llamar a todas tus funciones. Si no está utilizando argumentos con nombre, los argumentos cambiarán aleatoriamente el orden en la estructura missingMethodNameArguments.
Entonces ahora 3 formas.
Si está utilizando ColdFusion 9.0 o superior, ahora hay una función llamada GetFunctionCalledName (). Devolverá lo que estás buscando. http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WS7cc222be8a31a47d-6e8b7083122cebfc8f2-8000.html
O
Use ColdSpring y la Programación Orientada a Aspectos ( http://www.coldspringframework.org/coldspring/examples/quickstart/index.cfm?page=aop ) para manejar esto por usted.
O
Use un cfthrow para generar un seguimiento de pila que tenga la información para usted:
<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>
Mi recomendación sería usar getFunctionCalledName, o si no está en CF 9 ColdSpring, ya que probablemente te compre otras cosas.
Bueno, puedes intentar esto:
<cffunction name="getFunctionName" returntype="any">
<cfset meta =getMetaData(this)>
<cfreturn meta.functions[numberOfFunction].name>
</cffunction>
He intentado varias cosas, y esto no es preciso ya que las funciones parecen agregarse a la matriz de funciones en orden alfabético inverso. Esto parece limitar (y no resolver el problema). Me imagino que se podría invocar un código nativo de Java, pero voy a tener que investigarlo.
Esto y Esto parecen lecturas interesantes sobre funciones internas relacionadas.
Re: La otra respuesta en coldspring. Encontré este artículo en profundidad sobre metadatos de función con coldspring.
Pregunta relacionada: ¿Cómo obtener el nombre del componente que se extiende en ColdFusion?