cfc中的函数局部变量

Omi*_*ron 4 coldfusion scope cfc coldfusion-9

在我被要求在冷融应用程序中查看一些奇怪的间歇性错误之前没有使用过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>
Run Code Online (Sandbox Code Playgroud)

是否var需要每个listCount变量设置,或者只是在最初宣布的时间将被添加?

Pet*_*ton 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"...>

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


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

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

由于这些变量不是使用cfset创建的,因此最简单的方法是使用名称前缀来确定范围 local.

由于您已经确定var了listCount变量的范围,因此您不需要在同一个函数中再次执行它 - 您可以选择使用<cfset local.listCount = local.listCount + 1>(或实际上<cfset local.listCount++ >),但这又是一个优先事项,不需要防止泄漏到变量范围.

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

当然,这只是这个功能 - 您还需要修复其他功能 - 一个简单的方法是使用varscoper工具扫描整个代码库并识别需要作用域的变量.