我是ColdFusion的新手,刚开始学习Ajax。我的问题是我在网上找到了一些很酷的编码来实现两个下拉菜单,其中第二个依赖于从第一个选择的内容。但目标是从选择查询中提取下拉列表中的所有值。
我正在使用我刚学到的绑定功能。第一次下拉的所有东西都正确拉动。问题虽然是第二个问题。我从AJAX记录器获得的错误是"Error invoking: Error Executing Database Query"
任何建议将不胜感激。还要提前感谢您的帮助。
select.cfc
<cfcomponent output="false">
<!--- Get array of Catagory Description types --->
<cffunction name="cat_description" access="remote" returnType="array">
<!--- Define variables --->
<cfset var data="">
<cfset var result=ArrayNew(2)>
<cfset var i=0>
<!--- Get data --->
<cfquery name="getServiceCat" datasource="SOME_DATABASE">
SELECT DISTINCT CAT_DESC
FROM service_table
ORDER BY CAT_DESC
</cfquery>
<!--- Convert results to array--->
<cfloop index="i" from="1" to="#getServiceCat.recordcount#">
<cfset result[i][1]=getServiceCat.CAT_DESC[i]>
<cfset result[i][2]=getServiceCat.CAT_DESC[i]>
</cfloop>
<!--- And return it --->
<cfreturn result>
</cffunction>
<!--- Get Service Type by Cat description type --->
<cffunction name="getServiceType2" access="remote" returnType="array">
<cfargument name="CAT_DESC" type="string" required="true">
<!--- Define variables --->
<cfset var data="">
<cfset var result=ArrayNew(2)>
<cfset var i=0>
<!--- Get data --->
<cfquery name="getServiceType2" datasource="SOME_DATABASE" dbtype="query">
SELECT DISTINCT com_service_code, report_desc
FROM service_table
WHERE CAT_DESC = #ARGUMENTS.CAT_DESC#
ORDER BY report_desc
</cfquery>
</cfif>
<!--- Convert results to array --->
<cfloop index="i" from="1" to="#getServiceType2.recordcount#">
<cfset result[i][1]=getServiceType2.com_service_code[i]>
<cfset result[i][2]=getServiceType2.report_desc[i]>
</cfloop>
<!--- And return it --->
<cfreturn result>
</cffunction>
</cfcomponent>
以上是处理所有查询的cfc。此解决方案的主要原因之一是表单中所需的代码的简单性。
...
<td>Select Category: <cfselect name="catdesc"
bind="cfc:select.cat_description()"
bindonload="true"/><br />
</td>
...
<td>Select Service: <cfselect name="service"
bind="cfc:select.getServiceType2({catdesc})"
bindonload="false"/>
</td>
我已经搜索了将近2天,试图找到查询错误的解决方案。我知道查询在SQL中有效,所以我认为这个问题与AJAX有关,而且没有为第二次下拉正确实现WHERE子句。
同样,任何建议或建议都会很棒。另外,如果你以另一种方式做这个解决方案,我也很乐意尝试这个。正如我所说,我对这门语言很新。只有2周。
答案 0 :(得分:5)
测试CFC的
在将cfc插入ajax之前,始终在CF中测试cfc。在 后验证cfc没有错误地工作之前,没有必要搞乱绑定,因为如果它在CF中不起作用,它也不适用于ajax。唯一的区别是错误将更难找到。
正如其他人所说,从小处开始。单独测试查询。然后使用<cfinvoke>
继续测试CFC,或者只需使用以下测试值从浏览器调用它:
http://yourserver/path/to/select.cfc?method=getServiceType2&cat_desc=
http://yourserver/path/to/select.cfc?method=getServiceType2&cat_desc=someValue
错误强>
关于错误,我们需要查看完整的错误消息以提供更具体的建议。但是,查看查询/代码可能会导致:
CAT_DESC
是一个varchar列,在这种情况下,您的参数必须用单引号括起来。否则,数据库会认为参数值是对象名称(表或列)。
WHERE CAT_DESC = '#ARGUMENTS.CAT_DESC#'
.. OR CAT_DESC
是一个数字列,但您的参数为空。这将导致无效的sql语句。您需要确保将有效数字传递给查询(或者您可以在参数为空时跳过WHERE子句,具体取决于所需的结果)。一种常见的方法是使用val()
函数将空字符串和其他非数字值转换为零,即:
WHERE CAT_DESC = #val(ARGUMENTS.CAT_DESC)#
在第二次查询后,您看起来也有一个迷路</cfif>
。 (假设它不是复制/粘贴错误)
另一件事,您的第二个查询同时指定了datasource
和dbtype
。这两个属性是互斥的。让可能导致语法错误(我还没试过)。无论哪种方式,您都应该只使用其中一种(最有可能是datasource
)。
SQL注入
那就是说 - 上面的查询很容易被sql注入。您应该始终在所有变量查询参数上使用<cfqueryparam>
来防止sql注入。它还有其他好处(性能,数据类型检查等)。但是sql注入保护是Web应用程序中最关键的。
<!--- substitute the correct type for your db column --->
WHERE CAT_DESC = <cfqueryparam value="#ARGUMENTS.CAT_DESC#"
cfsqltype="cf_sql_varchar">
<强>改进强>
从CF8.0.1 +开始,cfselect
可以绑定到查询对象(而不仅仅是数组)。因此,只需从函数返回原始查询,而不是构建数组。
<cffunction name="getServiceType2" access="remote" returnType="query">
<cfargument name="CAT_DESC" ....>
<cfset var data="">
<cfquery name="data" ..>
SELECT TheQueryColumnToDisplay, TheQueryColumnUsedForListValue
FROM ...
WHERE ...
</cfquery>
<cfreturn data>
</cffunction>
然后指定要用于display
和value
属性的列:
<cfselect name="service"
bind="cfc:select.getServiceType2({catdesc})"
display="TheQueryColumnToDisplay"
value="TheQueryColumnUsedForListValue" ...>
答案 1 :(得分:1)
我的建议是一次做一件事。针对您的具体情况,
首先,让您的查询使用cfquery标记。
其次,让它在函数内部工作,在函数中将参数传递给函数。
接下来,将函数放在cfc中,并使用cfc页面或通过创建对象并调用函数来调用它。
最后做绑定。
这种方法会使错误更加明显,以便您可以对它们采取一些措施。
其他观察