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) />