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

发布于 2024-12-01 17:36:16 字数 1268 浏览 0 评论 0原文

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

这是我的代码:

<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 protected]')#');

如何用正确的变量名替换“email”(#validate_email...),并且仍然使函数正常工作?我希望我已经让这个可以理解了!

I'm writing a function that loops through some info on a registration page. Within the loop I'm trying to call functions based on an array. What I'm having problems with is actually calling the functions properly, because I'm trying to incorporate a variable as part of the function name.

Here's my code:

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

So, I have three functions: validate_email, validate_uname, validate_pass. If I throw in a writeoutput(), and attempt to output the results of the function, they do not work.

Here's that code:

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

Now, I understand that when you're using writeoutput(), and you're calling a function, you need the hash symbol on either end. So, let's say I write it like this:

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

It won't work, because the second hash symbol cancels out the function call. This is how the function should ultimately look (email example):

writeoutput('#validate_email('[email protected]')#');

How can I replace 'email' (#validate_email...) with the proper variable name, and still have the function work? I hope I've made this understandable!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

中性美 2024-12-08 17:36:16

函数也是变量,因此您可以以同样的方式对数组、结构体和作用域使用括号表示法,您可以使用它来访问动态变量名称(以及动态函数名称)

例如:

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

嗯...不完全是。由于 Adob​​e ColdFusion 中的错误,它不能像这样工作(尽管在其他 CFML 引擎中,如 Railo),您必须将其分成两行,如下所示:(

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

这假设函数和字段都在variables 范围,如果不是,您需要引用它们所在的范围。)

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

在CF10上,有调用 函数。早期版本的 CF 需要使用 cfinvoke 标签。

(顺便说一句,CF10 确实添加了用括号表示法引用函数结果的反向功能,即 doSomething()[key] ,有时会很有用。)

Functions are variables too, so in the same way you can use bracket notation for arrays, structs, and scopes, you can use this to access dynamic variable names (and thus dynamic function names)

For example:

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

Well... not quite. Due to a bug in Adobe ColdFusion, that doesn't work like that (though it does in other CFML engines, like Railo), and you have to split it into two lines, like this:

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

(This assumes both function and fields are in the variables scope, if they're not you need to refer to whichever scope they're in.)

This method does have an issue if the function was in an object with state, it loses reference to those variables.

On CF10, there is the invoke function. Earlier versions of CF need to use the cfinvoke tag.

(As a side note, CF10 did add the inverse ability of referencing function results with bracket notation, i.e. doSomething()[key] which comes in useful at times.)

丑丑阿 2024-12-08 17:36:16

彼得的回答是正确的(除了我评论的“错误”参考)。如果不在 CFScript 块的中间,另一种选择是。采用字符串作为其 METHOD 属性值,并且显然可以采用任何喜欢的动态值。

这对您的具体情况没有多大帮助,但记住它很方便。

我不会使用评估()方法。

Peter's answer is spot on (except the "bug" reference that I commented on). One other option if one is not in the middle of a CFScript block is that <cfinvoke> takes a string as its METHOD attribute value, and that can - obviously - take any dynamic value one likes.

This ain't so uch help for your specific situation, but it's handy to bear in mind.

I would NOT use the evaluate() approach.

狼性发作 2024-12-08 17:36:16

我要补充的是,在 ColdFusion 6.1 和迁移到 Java 之前,evaluate() 始终被认为是对性能的诅咒,但从 6.1 开始,它所做的只是计算表达式,然后创建一个内联 PageContext,其中包含的字符串作为其代码。

非常光滑,非常高效。

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

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

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

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

并且它返回的任何内容都将分配给变量。结果。

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

I will add that before ColdFusion 6.1 and the move to Java, evaluate() was always considered anathema to performance, but since 6.1 all it does is evaluate the expression and then create an inline PageContext with the included string as its code.

Very slick, very performant.

So, the simplest and most straightforward way to achieve your aims is:

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

So assuming you have a field named "username", this will be the equivalent of following method call:

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

and whatever it returns will be assigned to variables.result.

In tests it actually outperforms the bracket-notation technique of reassigning a method to a new name. I don't have stats here at the moment but it's faster by a substantial margin because an include is faster (and happens in a different phase of parsing/compilation) than a variable assignment.

弥枳 2024-12-08 17:36:16

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

有很多很多方法可以实现这一点...现在只是抛出各种想法。

One other approach to this issue is to use a UDF such as the following:

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

If you need to you could this:

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

or wrap it up in tags and toss it into a CFC:

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

There are many, MANY ways to make this happen... just tossing various ideas out there now.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文