cfc中的函数局部变量

时间:2012-06-10 18:38:35

标签: coldfusion scope coldfusion-9 cfc

在我被要求在冷敷应用程序中查看一些奇怪的间歇性错误之前,没有使用过coldfusion。

在阅读了范围后,我认为问题是因为我的cfc函数中没有变量使用var关键字,并且在各种函数中使用了相同的变量名。所以据我所知,变量是在页面级别的范围,调用这些函数的不同线程将覆盖变量,导致“奇怪”的问题。

我的问题是这样做的正确方法是什么?

 <cfset var listCount = 0>
 <cfquery name="qGetElementsByType" dbtype="query" maxrows="#arguments.num_to_return#">
    SELECT elementId,
           title, PIhtml, Rerhtml,
           text, url, image, Rank, isPoll, pollId, subjectId
    FROM   arguments.element_query
    WHERE  <cfloop list="#arguments.element_type_id#" index="lcv">
               <cfif listCount GT 0>
                  OR
               </cfif>
               subjectid =  #lcv#
              <cfset listCount = listCount + 1>
           </cfloop>
</cfquery>

每次设置listCount变量时,还是只需要在初始声明时添加var

3 个答案:

答案 0 :(得分:9)

(我希望这个答案不会太冗长。我不认为现有的答案提供了足够的信息,但希望在其他方面没有走得太远......)


在CF中,有各种范围可以放置变量(application,session,url,cgi等)。

其中一些需要使用显式声明(例如,会话变量必须始终作用域),其他可以在读取变量时自动访问(例如,可以使用未编组的变量读取表单和url变量) - 有一个这里的优先顺序决定了为未范围的变量检查哪些范围。

此排序的最低范围是variables范围,它是适用于整个当前页面/对象实例的范围。

设置新变量时,如果没有范围,则会在variables范围内创建。由于这是一个全局范围,因此可以从同一函数的不同实例以及差异函数访问它,这会导致您知道的问题。


要防止变量进入全局变量范围,必须将其放在函数的local范围内。 (从技术上讲,您可以将其放在函数的arguments范围内,但这可能会让人感到困惑。)

在早期版本的CF中,没有办法显式访问本地范围 - 您需要使用var关键字才能在本地范围内创建变量 - 一旦创建它将始终优先(在读取和写入时)都在变量范围内。

使用CF9,local范围现在是一个“适当的”范围,可以显式访问,因此您可以编写<cfset var x = 0 />而不是使用<cfset local.x = 0 /> - 这样做的主要好处是当您创建一个无法使用var关键字的变量时,例如<cfquery name="local.qGetElementsByType" ...><cfloop index="local.lcv"...>

在第一次创建每个变量时,你仍然只需要需要来应用本地范围,以防止它进入变量范围 - 如果你愿意,后续的读取/更新可以是无范围的,就像它们一样在做范围时。
(虽然与未编码变量存在其他潜在的与范围相关的问题,例如<cfloop query="queryname">块内部,因此有些人会争辩说,无论如何都应该始终确定所有变量的范围。)


总之,要使您显示的代码安全,您需要确定范围:

    来自cfquery标记的
  • qGetElementsByType
  • 来自cfloop标签的
  • lvc

由于这些变量不是使用cfset创建的,因此最简单的方法是使用local.

为名称添加前缀

由于您已经var确定了listCount变量的范围,因此您不需要在同一个函数中再次执行此操作 - 您可以选择使用<cfset local.listCount = local.listCount + 1>(或确实<cfset local.listCount++ >)但是这是一个偏好问题,不需要防止泄漏到变量范围。

(旁注:理想情况下,您应该使用#lcv#周围的cfqueryparam标记来防止SQL注入 - 即使这是查询查询,这可能仍然是一个问题,并且最好安全地发挥它关于安全。)

当然,这就是这个功能 - 你还需要修复其他功能 - 一个简单的方法是使用 varscoper 工具扫描你的整个代码库并确定需要确定范围的变量。

答案 1 :(得分:2)

除了Evik在他的回答中所说的,你应该VAR 所有你的函数局部变量。 qGetElementsByTypelcv也应该是VARed。如果您使用的是CF9,则只需使用LOCAL范围对其进行范围调整,例如:local.qGetElementsByType等。

答案 2 :(得分:0)

我假设你的问题专门针对这一行:

<cfset listCount = listCount + 1>

不,你不需要在这一行再次使用var。

但是,如果在页面的后面,您尝试使用名为listCount的变量访问它,它将具有您刚刚运行的代码中的值,因此您需要重新创建它。