在Coldfusion 9中使用coldfusion.sql.QueryTable.next()
我正在尝试编写一个自定义标记,以特殊方式遍历一个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# => #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>
这里的输出会是这样的:
Purchase 120 has a negative total! Purchase 157 has a negative total! Purchase 157 has a null total, this may be caused by:
上述链接中描述的功能是否从CF9中删除?
自从2006年撰写文章以来,内部资料已经发生了明显变化。但是我怀疑您描述的确切功能在任何mx版本中可能都不存在。 代码和链接示例之间的一个主要区别是<cfoutput query="..">
(不仅仅是一个普通的<cfoutput>
)的<cfoutput>
。 query
属性显然在评估变量时提供了一些额外的上下文。 删除它(如你的例子),结果是“第一行的值,而不是currentRow。”。 即使在MX6下,对于后续版本也不是好兆头。 确切的功能可能不会被删除。 它从未开始工作。
如果是的话还有其他选择吗?
就像我之前说的,最#query.column[row]#
方法是使用数组概念,即#query.column[row]#
。 鉴于你似乎拒绝了这个选项,你基本上只剩下evaluate()
。 您需要遍历父标记中的查询。 然后使用evaluate
来处理子标签表达式和内容。 这不是特别优雅或简单的国际海事组织。 但我认为这可能是好的,因为它没有数组符号,或某种仪式的牺牲。
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
注:请不要使用<cfoutput>
标签内容中的标签。
<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最相似,也就是说舒适吗?
内部平台效应的典型例子。
我建议你不要这样做,因为你正在试图创建一个模仿基础或运行系统的内置功能的系统,这个系统最终会成为它运行/实现的系统的一个执行不当的版本。
听起来令人困惑,我知道 - 但这是一个众所周知的反模式,以避免。
有关更多信息,请参阅此处:http://en.wikipedia.org/wiki/Inner-platform_effect
Ps你在找什么(虽然我不同意这个实现)是cfloop之外的查询的迭代,只需使用数组语法:
#queryName.fieldName[rowNumber]#
使用这个你可以按照你想要的方式来查询查询,当然不需要基础的java。 注意我们没有使用queryName.currentRow。 对于previous()next()功能,您只需向上或向下更改rowNumber。
链接地址: http://www.djcxy.com/p/74057.html上一篇: Using coldfusion.sql.QueryTable.next() in Coldfusion 9
下一篇: Best practice Fetch user's information from the Firebase User UID