【问题标题】:Automatic Type Conversion in ColdFusion 11ColdFusion 11 中的自动类型转换
【发布时间】:2014-12-12 16:19:02
【问题描述】:

我正在将应用程序从 ColdFusion 9 迁移到 ColdFusion 11。

在现有代码中有一个变量赋值给false

<cfset VARIABLES.roleTypeId = false >

然后,再往下,一个函数期望这个变量是数字的:

<cffunction name="rolesForStudy" >
    <cfargument name="id" hint="Study Id">
    <cfargument name="roleTypeId" default="#VARIABLES.roleTypeId#" type="numeric"/>
</cffunction>

我继承了代码,我不能为最初程序员以这种方式设置它的决定辩护——但简而言之,它在 ColdFusion 9 中工作,但它没有在 ColdFusion 11 中工作(返回数据类型错误)。我假设 ColdFusion 9 会自动将 false 转换为 0

我的问题:我可以在 ColdFusion 11 中更改配置设置以使其像 ColdFusion 9 那样进行转换吗?或者我是否必须修复此代码以及整个应用程序中可能存在的许多其他类似示例?我和我们的 ColdFusion 管理员都无法在 ColdFusion 管理员界面、ColdFusion 文档或在线中找到任何相关信息。

编辑以回应 cmets 中的 Adam Cameron

我创建了一个包含以下 10 行的文件(仅此而已):

<cfset VARIABLES.roleTypeId = false >
<cfoutput>
<p>#rolesForStudy( 1, VARIABLES.roleTypeId )#</p>
</cfoutput>

<cffunction name="rolesForStudy" >
    <cfargument name="id" hint="Study Id">
    <cfargument name="roleTypeId" default="#VARIABLES.roleTypeId#" type="numeric"/>
    <cfreturn "It worked" >
</cffunction>

当我在 ColdFusion 9 中执行它时,它会显示“It works”字样。

当我在 ColdFusion 11 中执行它时,它返回以下错误消息:
如果将组件名称指定为此参数的类型,则可能无法定义组件的定义文件找到或无法访问。

【问题讨论】:

  • 无论您的问题是什么,将 false 转换为数字都不是问题(它会转换为 0 就好了)。这种行为在 ColdFusion 11 中没有改变。你能提供一个适当的重现案例来展示你所看到的吗?还提供确切的错误(从屏幕复制和粘贴)。也可以付费阅读:blog.adamcameron.me/2013/09/…
  • Holy f***(刚刚在这里运行了你更新的代码。我也一样。WTF?!调查它)

标签: coldfusion


【解决方案1】:

我相信您将不得不修复代码。没有任何设置(我无论如何都知道)会改变 CF 处理布尔类型的方式。您应该能够将上面的分配从“false”更改为 0,并且您的功能代码将起作用。但是我怀疑在其他地方你可能有类似&lt;cfif variables.roletypeID IS "False"&gt; 的东西,然后它会被破坏,因为它实际上是在寻找一个字符串 - 工作(ha)。 CF 将无数值处理为布尔值(0 或非 0、真、假、是和否)是其起源的遗产。有时很方便,但肯定会导致这样的事情。

与此同时,我想知道这种行为变化是新错误还是旧错误的修复。在我看来,将“false”作为参数传递并将其读取为数字似乎不一致,因此 new 这样做的方式对我来说似乎是正确的。但是,许多语言将 0 或非 0 视为 true 和 false 的默认值。

编辑:

根据下面亚当的 cmets,我的代码示例有人会说:

<cfif somevar IS "false">

...即使 somevar 确实是数字也可以工作。他的例子(有用)是:

#0 is "False"#

...将输出 "yes" - 因此 CF 将字符串 "false" 在引擎盖下重铸为零以进行比较。这使我的例子不正确。

我相信我的回答仍然是正确的。他遇到的问题是传递给他的函数的参数 - “布尔”类型会引发错误,因为函数需要一个数值。但是亚当的观点和例子让我认为这种行为可能是一个错误 - 因为它似乎 CF 在检查类型之前没有强制转换为数字(根据乔的说法,它在 CF 9 中 确实做了)。

【讨论】:

  • 谢谢。在我将其中任何一个标记为正确之前,我想看看是否有任何其他答案出现——但我已经对你的回复表示赞同。您的回答与我的假设相符,但我希望比我更熟悉 ColdFusion 的人有一个解决方案,可以让我避免大量代码重构。
  • 是的......这里可能有一些精明的 Java 人知道一些晦涩的属性:)
  • 这是一个很好的跨应用程序维护数据类型的课程。正如邓肯所指出的,Numberformat 确实有效(奇怪的是 val() 在 Railo 中有效,但在 CF 中无效(至少是 9 - 有人想测试吗?)。尽管如此,虽然 Duncan 的解决方案有效,但创可贴有闯入的习惯意想不到的方式。最好保持一致。
  • 马克,对不起,但问题不是 OP 声称的那样。例如这个输出Yes:&lt;cfoutput&gt;#0 is "false"#&lt;/cfoutput&gt;。从那以后它就已经是 CFMX7 (在此之前,像这样的内联表达式将是一个语法错误。CF - 所有版本 - 都会在必要时将布尔值转换为数字。这是 not 的答案问题(并已否决,抱歉)
  • 亚当,是的,我看到您在我能够检查的版本中是正确的。我编辑了我的答案并添加了您的信息。我想知道“严格类型检查”是否在这里有任何影响?
【解决方案2】:

NumberFormat 是您的救星,感谢 Ben Nadel 的一篇文章中的 this comment

<cfset VARIABLES.roleTypeId = false>
#NumberFormat(VARIABLES.roleTypeId)# <!-- = 0 -->
<cfset VARIABLES.roleTypeId = true>
#NumberFormat(VARIABLES.roleTypeId)# <!-- = 1 -->

所以你应该能够在调用函数之前将其转换为预期的数字类型,或者只是这样做

<cfargument name="roleTypeId" default="#NumberFormat(VARIABLES.roleTypeId)#" type="numeric">

【讨论】:

  • 很好的发现,我发现 NumberFormat 确实有效,但 Val() 无效(在 ACF9 中,它在 Railo 中有效),这真的很令人惊讶。不过,我希望 OP 只是更正代码。我只是发现Int() 也可以。不过,我希望 OP 只是修复旧代码。
  • 你不需要投射它。请参阅我对问题的评论和马克的回答。
  • @cfqueryparam - 你是什么意思val() 不起作用? “false”(或“true”)的开头没有数字字符,因此它应该返回零 (0)。它在 Railo 中有什么不同吗?
  • @Leigh 在这个问题之前,我从未尝试过 Val(true) 来看看会发生什么。我在应用程序之间保持兼容的值,但由于 NumberFormat() 确实有效,我有一种预期的 Val() 可以工作,所以尝试了一下。在 CFLive.net 上,CF9 对真/假都返回 0(就像 val 对每个非数字值一样),但 Railo 对真返回 1。
  • @cfqueryparam - 嗯.. NumberFormatfalse 隐式转换为数字是有意义的。这符合 CF 对data conversion 的规则。但是,the purpose of val 不同:将出现在字符串开头的数字字符转换为数字。 鉴于此,Railo 的结果听起来是错误的。
【解决方案3】:

我已将此作为 ColdFusion 11 中的错误提出:“Type coercion failure when passing boolean to a numeric arg”。

我建议您通过取消参数的类型检查来解决此问题。这可能是影响最小的修复。

这也是一种罕见的情况,我会在代码中添加注释,解释为什么你取消了类型检查。

向 Joe、Mark 和 Duncan 道歉,因为他们强烈反对他们的发现。也就是说,我不同意他们的答案是这里最好的方法;-)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-13
    • 2011-01-25
    • 1970-01-01
    • 1970-01-01
    • 2011-12-28
    • 2014-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多