Function 如何在ColdFusion中将变量名作为函数名的一部分调用?

Function 如何在ColdFusion中将变量名作为函数名的一部分调用?,function,variables,coldfusion,Function,Variables,Coldfusion,我正在写一个函数,它循环浏览注册页面上的一些信息。在循环中,我尝试调用基于数组的函数。我遇到的问题实际上是正确调用函数,因为我试图将变量作为函数名的一部分合并 这是我的密码: <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) { fu

我正在写一个函数,它循环浏览注册页面上的一些信息。在循环中,我尝试调用基于数组的函数。我遇到的问题实际上是正确调用函数,因为我试图将变量作为函数名的一部分合并

这是我的密码:

<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>
它不会工作,因为第二个哈希符号会取消函数调用。这就是函数最终的外观(电子邮件示例):


如何用正确的变量名替换“email”(#validate_email…)并使函数仍能工作?我希望我能理解这一点

函数也是变量,因此可以用括号表示数组、结构和作用域,也可以用括号表示访问动态变量名(从而访问动态函数名)

例如:

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

...
嗯。。。不完全是。由于Adobe ColdFusion中的一个bug,它的工作方式与此不同(尽管在其他CFML引擎中,如Railo),您必须将其分成两行,如下所示:

writeoutput('#validate_#func[2]#(#fields[i]#)#');
<cfloop index="Field" list="email,uname,pass">
    <cfset TmpFunc = Variables['validate_'&Field] />
    <cfset Result = TmpFunc( Variables['r_'&Field] ) />
    ...
</cfloop>

...
(这假设函数和字段都在
变量范围内,如果它们不在范围内,则需要引用它们所在的范围。)

如果函数位于状态为的对象中,则此方法确实存在问题,它会丢失对这些变量的引用

在CF10上,有一个函数。CF的早期版本需要使用标记


(作为旁注,CF10确实添加了使用括号表示法引用函数结果的反向功能,即,
doSomething()[key]
,这有时很有用。)

Peter的答案很正确(我评论的“bug”引用除外)。如果一个不在CFScript块的中间,另一个选项是将字符串作为其方法属性值,并且可以很明显地获取任何一个喜欢的动态值。 这对你的具体情况没有多大帮助,但要记住这很方便


我不会使用evaluate()方法。

我要补充的是,在ColdFusion 6.1和迁移到Java之前,evaluate()一直被认为是性能的诅咒,但由于6.1,它所做的只是计算表达式,然后创建一个内联页面上下文,其中包含的字符串作为其代码

非常圆滑,非常出色

因此,实现目标最简单、最直接的方法是:

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

因此,假设您有一个名为“username”的字段,这将相当于以下方法调用:

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

它返回的任何内容都将分配给variables.result


在测试中,它实际上优于将方法重新指定给新名称的括号表示法技术。目前我这里没有统计数据,但速度要快很多,因为include比变量赋值更快(并且发生在解析/编译的不同阶段)。

解决此问题的另一种方法是使用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) />


有很多很多方法可以让这一切发生。。。现在只是抛出各种各样的想法。

这不是CF中的错误,彼得:只是从来没有被实现过。您可能希望修改您的评论以达到此效果。否则答案会有点错误。
Variables.Bob()
Variables['Bob']()
-但是,第二个变量会抛出一个错误。我称之为括号中的错误符号,而不是未实现的特性。谢谢。我收到的两个建议都很有效。我是CF新手,所以我会随大流,使用这个而不是另一个。另一个比较简单,但如果有问题,我不想谈这个!再次感谢!至于Adam对evaluate()的警告,除了愚蠢并使用它来评估用户提供的值(比如允许用户本质上键入代码-是的,已经完成了),没有理由避免使用这种方法。没有遗留的性能或安全问题。
    <cfinclude template="invokerudf.cfm" />
    <cfscript>...</cfscript>
<cfset retval = createObject("methodinvoker").callMethod(methodName,methodArgs) />