将会话从CFScript转换为ColdFusion标记语法

时间:2013-06-05 18:48:31

标签: coldfusion coldfusion-8 cfml

应用程序: JavaScript函数侦听表单元素的更改(输入和选择),并将数据发布到将它们分配给Session结构的CFC方法。返回结构,使表单数据可用于会话的生命周期。该应用程序改编自Raymond Camden's Using a server, or session storage, to persist form values的代码。

问题:原始CFC代码是用CFScript编写的。因为我们在ColdFusion 8上,所以在调用方法时会出错。因此,我将该方法转换为ColdFusion标记语法并停止获取该错误。在Chrome的开发工具中,每当我在表单元素中输入内容时,我都会看到通过JSON对象传递到CFC的数据。所以我知道JavaScript函数正在运行。即使我没有收到任何返回错误,也有一些行为让我相信我的翻译不正确。例如,会话结构的转储仅显示输入的最后一个输入元素,而不是所有输入元素(就像Ray的演示中的情况一样)。

这是原始的CFScript版本,然后是我的标签翻译。除了关于我的翻译错误的任何评论之外,我很乐意对这一行<cfset s.name = [s[name]] />,特别是[s[name]]结构进行解释,因为我无法清楚地说明那里发生的事情。 。感谢。

脚本语法:

component {
    remote void function preserveSession(string awardData) {
        if(!isJSON(arguments.awardData)) return;
        arguments.awardData = deserializeJSON(arguments.awardData);

        //convert the array into a name based struct
        var s = {};
        for(var i=1; i<=arrayLen(arguments.awardData); i++) {
            var name = arguments.awardData[i].name;
            if(!structKeyExists(s, name)) {
                s[name] = arguments.awardData[i].value;    
            } else {
                //convert into an array
                if(!isArray(s[name])) {
                    s[name] = [s[name]];
                }
                arrayAppend(s[name], arguments.awardData[i].value);
            }    
        }
        session.awardFormData = s;    
    }
}

标记语法:

<cfcomponent>
    <cffunction name="preserveSession" access="remote" returntype="void" output="no">

        <cfargument name="awardData" type="string" />

        <cfset var s = {} />

        <cfif NOT isJSON(arguments.awardData)>
            <cfreturn />
        </cfif>

        <cfset arguments.awardData = #deserializeJSON(arguments.awardData)# />

        <cfloop index="i" from="1" to="#arrayLen(arguments.awardData)#">
            <cfset name = #arguments.awardData[i].name# />

            <cfif NOT structKeyExists(s, name)>
                <cfset s.name = #arguments.awardData[i].value# />   
            <cfelse>
                <cfif NOT isArray(s.name) >
                    <cfset s.name = [s[name]] />
                </cfif>
                <cfset arrayAppend(s.name, arguments.awardData[i].value) />
            </cfif>
        </cfloop>

        <cfset session.awardFormData = s />

        <cfreturn />
    </cffunction>
</cfcomponent>

2 个答案:

答案 0 :(得分:5)

首先,你真的不需要翻译所有这些。 CF8不支持cfscript中的组件/功能,但您可以按原样使用它:

<cfcomponent>
  <cffunction name="preserveSession" access="remote" returntype="void" output="no">
    <cfargument name="awardData" type="string" />
      <cfscript>
        var s = {};
        var name = '';
        var i = 0;
        if(!isJSON(arguments.awardData)) return false;
        arguments.awardData = deserializeJSON(arguments.awardData);
        for(i=1; i<=arrayLen(arguments.awardData); i++) {
          name = arguments.awardData[i].name;
          if(!structKeyExists(s, name)) {
            s[name] = arguments.awardData[i].value;
          } else {
            if(!isArray(s[name])) {
              s[name] = [s[name]];
            }
            arrayAppend(s[name], arguments.awardData[i].value);
          }
        }
        session.awardFormData = s;
        return true;
    </cfscript>
  </cffunction>
</cfcomponent>

尝试简单地重写这样的内容,而不是重写,看看你是否走得更远。

通常解释符号: s[name]通过s中存储的值的键来解决name的结构;这有时称为数组表示法。 它相当于名称已知的s.theValueStoredInName的点符号。 要动态地通过变量名称来解决结构,最简单的方法是通过数组表示法来实现。

嵌套集的相同之处: 行s[name] = [s[name]]正在设置一个键,其值为name中存储的值s[name]的命名键中存储的值。通过将该集包装在[]中,它就是一种数组。

这将有助于明确具体说明:

如果尚未将具有该name-key的内容指定为结构,则将其存储为结构(简单名称 - 键值)。 如果有,则将name-key值中的内容转换为具有该name-key的数组。 那么如果是第二项的连续的传递(它会有的,如果有!只是检查,如果这个数组转换已经发生了至少一次),然后是第二项追加到阵列具有的关键一样的名字。

就个人而言,为了简单起见,我总是直接设置为数组。然后,您始终知道如何处理存储中的值。

答案 1 :(得分:2)

  

<cfset s.name = ... />

您需要动态访问密钥名称。上面的代码每次都使用相同的静态密钥(即name)。因此,每次循环时最终都会覆盖以前的值。这就是为什么你最终只得到一个值 - 最后一个。

 <!--- this creates a dynamic key named "apple" (correct) --->
 <cfset name = "apple" />
 <cfset s[name] = "..." />

 <!--- this creates a key literally named "name" (wrong) --->
 <cfset name = "apple" />
 <cfset s.name = "..." />

要解决此问题,无论您在使用s.name的任何地方,请将其替换为s[name]。另外,不要忘记var范围所有函数局部变量。

更新:

williambq's response也提出了一个很好的观点。您不必将它全部转换为cfml。将它的大部分包装在cfscript标签中更简单。