Может ли метод cfc ColdFusion определить свое имя?
Я создаю API, и в каждом методе я делаю вызов метода ведения журнала для аудита и устранения неполадок. Что-то вроде:
<cffunction name="isUsernameAvailable">
<cfset logAccess(request.userid,"isUsernameAvailable")>
......
</cffunction>
Я бы хотел, чтобы вручную не повторять имя метода. Есть ли способ его программно определить?
Я просмотрел GetMetaData(), но только возвращает информацию о компоненте (включая все методы), но ничего о том, какой метод в данный момент вызывается.
Ответы
Ответ 1
Итак, теперь 3 способа.
Если вы используете ColdFusion 9.0 или выше, теперь есть функция с именем GetFunctionCalledName(). Он вернет то, что вы ищете.
http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WS7cc222be8a31a47d-6e8b7083122cebfc8f2-8000.html
ИЛИ
Используйте ColdSpring и Aspect Oriented Programming (http://www.coldspringframework.org/coldspring/examples/quickstart/index.cfm?page=aop), чтобы справиться с этим для вас.
ИЛИ
Используйте 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, так как она, вероятно, купит вам некоторые другие вещи.
Ответ 2
Я согласен w/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 добавила поддержку для циклического перебора файлов по строкам (и не считывает весь файл в память). Я провел несколько тестов, сравнивающих метод трассировки стека и синтаксический анализ файлов. Оба одинаково хорошо работали на небольшом CFC, который вызывается непосредственно из одного шаблона CFM. Очевидно, что если у вас очень большие CFC, метод анализа может быть немного медленнее. С другой стороны, если у вас большая трассировка стека (например, если вы используете какую-либо из популярных фреймворков), тогда анализ файлов может быть быстрее.
- = Viva ColdFusion = -
Ответ 3
Ну, вы можете попробовать следующее:
<cffunction name="getFunctionName" returntype="any">
<cfset meta =getMetaData(this)>
<cfreturn meta.functions[numberOfFunction].name>
</cffunction>
Я пробовал разные вещи, и это неточно, поскольку функции, похоже, добавляются в массив функций в обратном алфавитном порядке. Это кажется ограниченным (и не решает проблему). Я бы предположил, что можно использовать какой-то собственный Java-код, но мне нужно будет изучить это.
Это и Это выглядит как интересное чтение о связанных внутренних функциях.
Re: Другой ответ на coldspring. Я нашел эту статью подробно о метаданных функций с coldspring.
Связанный вопрос: Как получить имя компонента, который расширяет мой в ColdFusion?
Ответ 4
Я думал о другом способе, который мог бы работать.
Настроить 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, который добавит имя метода к аргументам, которые передаются реальному методу.
Недостатки, которые я вижу в этом, - это то, что интроспекция больше не работает должным образом, и вы должны использовать именованные аргументы для вызова всех своих функций. Если вы не используете именованные аргументы, аргументы будут случайным образом изменять порядок в структуре missingMethodNameArguments.