【问题标题】:Using coldfusion.sql.QueryTable.next() in Coldfusion 9在 Coldfusion 9 中使用 Coldfusion.sql.QueryTable.next()
【发布时间】:2011-07-25 15:07:06
【问题描述】:

我正在尝试编写一个自定义标记,该标记将以特殊方式迭代 cfquery 对象。我找到了这个页面:http://www.zrinity.com/developers/mx/undocumentation/query.cfm 概述了如何使用底层 java 方法来导航结果集,但它似乎在 CF9 中不起作用。

我可以调用.next().previous().first().last()就好了,每个方法都会更新query.currentRow,但引用query.columnName总是返回第一行的值,而不是currentRow。

例子:

<cfquery name="testQuery" datasource="source">
  SELECT FooName FROM NumberedFoos
</cfquery>

<cfloop from="1" to="3" index="i">
  <cfoutput>#testQuery.currentRow# =&gt; #testQuery.fooName#</cfoutput><br />
  <cfset testQuery.next()>
</cfloop>

生产:

1 => Foo 1
2 => Foo 1
3 => Foo 1

我知道我可以使用testQuery.fooName[testQuery.currentRow] 之类的东西,但这对于我为其制作自定义标签的人来说是非常不受欢迎的。上述链接中描述的功能是否已从 CF9 中删除?如果有,有没有替代品?

编辑

为了扩展原因,客户需要一个自定义标签,允许他们“断言”关于查询的某些事情。客户对 CF 的理解水平很低,但编写 SQL 相当扎实。他们想要的最终结果类似于:

<cfquery name="purchaseTotals">
  SELECT PurchaseId, Total FROM Purchases
</cfquery>

<CF_ASSERT query="purchaseTotals">
  purchaseTotals.Total gte 0
</CF_ASSERT>

所需的输出将是一个 html 表,其中每一行都是断言失败的查询中的行。所以对我来说,CF_ASSERT 标签需要能够更新当前行。

编辑 2:

主要挑战是在标签正文中允许使用 html,同时仍然从适当的行替换查询值:

<CF_ASSERT query="purchaseTotals">
  <CF_CONDITION expression="purchaseTotals.Total gte 0">
    <!---error message when expression is false--->
    <cfoutput>
      Purchase #purchaseTotals.purchaseId# has a negative total!
    </cfoutput>
  </CF_CONDITION>
  <CF_CONDITION expression="purchaseTotals.Total eq ''">
    #PurchaseTotals.purchaseId# has a null total, this may be caused by:
    <ul>
      <li>Edge Case 1</li>
      <li>Edge Case 2</li>
    </ul>
  </CF_CONDITION>
<CF_ASSERT>

这里的输出是这样的:

购买 120 的总数为负数! 购买 157 的总数为负数! 购买 157 的总计为空,这可能是由于:
  • 边缘案例 1
  • 边缘案例 2

【问题讨论】:

  • Re: “这对于我为其制作自定义标签的人来说是非常不受欢迎的” 为什么?这是完全有效的语法。我认为使用 undocumented 功能会更不可取。
  • 同意它是有效的语法,但目标用户并不真正理解索引。他们希望它尽可能接近 ,这允许对当前行的列进行非索引引用。
  • 如果这将在自定义标签中,您的客户甚至会关心自定义标签中的内容吗?如果你的 cfloop 在标签中,你不能让它引用你的循环变量来获取当前值吗?还是我错过了什么?
  • @Limey:对行的引用在标签的正文中,而不是在标签的实现中。请参阅我的编辑澄清。我很舒服(而且我确实)使用标签实现中的索引。
  • @adharris - 也许还有更多,但为什么“purchaseTotals.Total gte 0”不仅仅是标签的属性(或处理方式)?或者他们是否也在定义所需的输出......?

标签: coldfusion coldfusion-9


【解决方案1】:

上述链接中描述的功能是否已从 CF9 中删除?

自 2006 年撰写这篇文章以来,内部内容肯定发生了变化。但我怀疑您所描述的确切功能可能不存在于任何 mx 版本中。您的代码和链接示例之间的主要区别在于 &lt;cfoutput query=".."&gt; 的使用(不仅仅是普通的 &lt;cfoutput&gt;)。在评估变量时,query 属性显然提供了一些额外的上下文。删除它(就像在你的例子中一样),结果是“第一行的值,而不是 currentRow。”。即使在 MX6 下,对于后续版本来说也不是好兆头。那个确切的功能可能没有被删除。它只是从一开始就没有用。

如果有,还有其他选择吗?

就像我之前说的,最简洁的方法是使用数组概念,即#query.column[row]#。鉴于您似乎拒绝了该选项,您基本上只剩下evaluate()。您需要遍历父标签中的查询。然后使用evaluate处理子标签的表达和内容。它不是特别优雅或简单的 IMO。但我认为这可能会很好,因为它没有数组符号或某种仪式牺牲。

ASSERT.cfm

<cfparam name="attributes.query" type="string">

<cfif thisTag.ExecutionMode is 'start'> 
    <!--- validate attributes.query is a query object --->
    <cfif not ( structKeyExists(caller, attributes.query) AND IsQuery(caller[attributes.query]) )>
        <cfthrow message="Attributes.query [#attributes.query#] is undefined or not a query object">
    </cfif>
</cfif>
<cfif thisTag.ExecutionMode is 'end'> 
    <cfset variables[attributes.query] = caller[attributes.query]> 
    <cfloop query="variables.#attributes.query#">
        <cfloop array="#thisTag.assocAttribs#" index="subTag">
            <cfset variables.matchFound = evaluate(subTag.expression)>
            <cfif variables.matchFound>
                <cfoutput>[#currentRow#] #evaluate(DE(subTag.Content))#</cfoutput><hr>
            </cfif>
        </cfloop>
    </cfloop>
</cfif>

CONDITION.cfm
注意:NOT在标签内容中使用&lt;cfoutput&gt; 标签。

<cfparam name="attributes.expression" type="string">
<cfif thisTag.ExecutionMode is "start"> 
    <cfassociate baseTag="CF_ASSERT">
</cfif>
<cfif thisTag.ExecutionMode is "end"> 
    <cfset attributes.content = thisTag.GeneratedContent>
    <cfset thisTag.GeneratedContent = "">
</cfif>

客户对 CF 的理解水平很低,但很漂亮 扎实的编写SQL

说了这么多,以这种方式实现是因为它是最好的方法还是因为它最类似于编写 SQL 即舒适?

【讨论】:

    【解决方案2】:

    内平台效应的经典例子。

    我建议您不要这样做,因为您正在尝试创建一个模仿基本或运行系统的内置功能的系统,最终成为运行/实现它的系统的一个实施不佳的版本。

    我知道这听起来令人困惑 - 但这是一个众所周知的要避免的反模式。

    更多信息请看这里:http://en.wikipedia.org/wiki/Inner-platform_effect

    附:您正在寻找的(尽管我不同意实现)是在 cfloop 之外迭代查询,只需使用数组语法:

    #queryName.fieldName[rowNumber]#
    

    使用它你可以随心所欲地迭代查询,当然不需要底层的java。请注意,我们没有使用 queryName.currentRow。对于 previous() next() 功能,您只需向上或向下更改 rowNumber。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-13
      • 1970-01-01
      • 1970-01-01
      • 2011-04-02
      • 1970-01-01
      相关资源
      最近更新 更多