Как я могу вызвать имя переменной как часть имени функции в ColdFusion? - PullRequest
6 голосов
/ 26 августа 2011

Я пишу функцию, которая просматривает некоторую информацию на странице регистрации. В цикле я пытаюсь вызывать функции на основе массива. У меня проблемы с тем, чтобы на самом деле вызывать функции должным образом, потому что я пытаюсь включить переменную как часть имени функции.

Вот мой код:

<cfscript>
fields = arraynew(1);
fields[1] = 'r_email';
fields[2] = 'r_uname';
fields[3] = 'r_pass';

for(i = 1; i lte arraylen(fields); i = i + 1)
{
    func = fields[i].split('r_');
    func = 'validate_#func[2]#(#fields[i]#)';
}
</cfscript>

Итак, у меня есть три функции: validate_email, validate_uname, validate_pass. Если я добавлю writeoutput () и попытаюсь вывести результаты функции, они не будут работать.

Вот этот код:

<cfscript>
fields = arraynew(1);
fields[1] = 'r_email';
fields[2] = 'r_uname';
fields[3] = 'r_pass';

for(i = 1; i lte arraylen(fields); i = i + 1)
{
    func = fields[i].split('r_');
    func = 'validate_#func[2]#(#fields[i]#)';
    writeoutput('#func#');
}
</cfscript>

Теперь я понимаю, что когда вы используете writeoutput () и вызываете функцию, вам нужен хеш-символ на любом конце. Итак, допустим, я пишу это так:

writeoutput('#validate_#func[2]#(#fields[i]#)#');

Это не сработает, потому что второй хэш-символ отменяет вызов функции. Вот как в конечном итоге должна выглядеть функция (пример электронной почты):

writeoutput('#validate_email('email@site.com')#');

Как я могу заменить 'email' (#validate_email ...) на правильное имя переменной, и при этом работать с функцией? Надеюсь, я сделал это понятным!

Ответы [ 4 ]

11 голосов
/ 26 августа 2011

Функции также являются переменными, поэтому таким же образом вы можете использовать скобочные обозначения для массивов, структур и областей, вы можете использовать их для доступа к динамическим именам переменных (и, следовательно, к динамическим именам функций)

Например,:

<cfloop index="Field" list="email,uname,pass">
    <cfset Result = Variables['validate_'&Field]( Variables['r_'&Field] ) />
    ...
</cfloop>

Ну ... не совсем.Из-за ошибки в Adobe ColdFusion это не работает (хотя это происходит в других механизмах CFML, таких как Railo), и вам нужно разбить ее на две строки, например:

<cfloop index="Field" list="email,uname,pass">
    <cfset TmpFunc = Variables['validate_'&Field] />
    <cfset Result = TmpFunc( Variables['r_'&Field] ) />
    ...
</cfloop>

(Предполагается, что и функция, и поля находятся в области действия variables, если они не нужны, вам нужно ссылаться на ту область, в которой они находятся.)

Этот метод имеет проблему, если функция находилась вобъект с состоянием теряет ссылку на эти переменные.

На CF10 есть функция invoke.Более ранние версии CF должны использовать тег cfinvoke.

(В качестве примечания к CF10 добавлена ​​обратная возможность ссылки на результаты функции с помощью скобок, т. Е. doSomething()[key], которая иногда бывает полезна.)

1 голос
/ 26 августа 2011

Ответ Питера точен (кроме ссылки на «ошибку», которую я прокомментировал).Еще один вариант, если он находится не в середине блока CFScript, это то, что принимает строку в качестве значения атрибута METHOD, и это может - очевидно - принимать любое динамическое значение, которое нравится.

ЭтоЭто очень полезно для вашей конкретной ситуации, но это полезно иметь в виду.

Я бы НЕ использовал подход оценки ().

0 голосов
/ 25 марта 2015

Еще один подход к этой проблеме - использовать UDF, например:

    <cffunction name="callMethod">
        <cfargument name="methodName" type="string" required="true" />
        <cfargument name="methodArgs" type="struct" default="#{}#" />
        <cfset var rslt = 0 />
        <cfinvoke method="#arguments.methodName#" argumentcollection="#arguments.methodArgs#" returnvariable="rslt" />
        <!--- account for the possibility that the method call wiped out the rslt variable --->
        <cfif structKeyExists(local,'rslt')>
            <cfreturn rslt />
        </cfif>
    </cffunction>

Если вам нужно, вы можете это сделать:

    <cfinclude template="invokerudf.cfm" />
    <cfscript>...</cfscript>

или обернуть его впометить и выбросить в CFC:

<cfset retval = createObject("methodinvoker").callMethod(methodName,methodArgs) />

Существует множество МНОГИХ способов сделать это ... просто выбрасывая различные идеи.

0 голосов
/ 25 марта 2015

Я добавлю, что перед ColdFusion 6.1 и переходом на Java метод execute () всегда считался анафемой производительности, но начиная с версии 6.1 все, что он делает - это вычисляет выражение, а затем создает встроенный PageContext с включенной строкой в ​​качестве кода.

Очень гладкий, очень производительный.

Итак, самый простой и простой способ достижения ваших целей:

<cfset result = evaluate("validate_#Field#(variables.r_#Field#)") />

Итак, если у вас есть поле с именем "username"", это будет эквивалентно следующему вызову метода:

<cfset result = validate_username(variables.r_username) />

, и все, что он возвращает, будет присвоено variables.result.

В тестах это фактически превосходит метод скобочных обозначенийпереназначение метода на новое имя.В данный момент у меня нет статистики здесь, но она быстрее с существенным запасом, потому что включение происходит быстрее (и происходит на другом этапе анализа / компиляции), чем присвоение переменной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...