1

我正在使用 ColdFusion 并尝试创建一个函数,该函数允许我获取特定帐户中特定列的值(每个帐户都是它自己的记录/行)。

像这样的功能可以正常工作:

<cffunction name="getColumnValueFromAccount" access="public" returntype="string" >
    <cfargument name="accountName" type="string" required="yes" />

    <cfquery name="getColumn" datasource="mydatasource">
        <!--- Note that the line below is 'hard-coded.' --->
        SELECT role_ExampleSystem
        FROM table_name
        WHERE (accountName = <cfqueryparam cfsqltype="cf_sql_varchar" maxlength="50" value='#accountName#'>)
    </cfquery>

    <!--- It's easy to return the column value when you know what its name was. --->
    <cfreturn getColumn.role_ExampleSystem > 

</cffunction>

但我真正想要的是一个函数,它允许我指定从哪个列名读取,并且不需要制作一堆几乎相同的 CF 函数,它们只是具有不同的硬编码 SELECT 参数。我认为它应该看起来像这样,但是我在实际读取我认为它应该返回的单个字符串时遇到了麻烦。

<cffunction name="getColumnValueFromAccount" access="public" returntype="string" >
    <cfargument name="accountName" type="string" required="yes" />
    <!--- Trying to accept a column name as an argument --->
    <cfargument name="columnName" type="string" required="yes" />

    <cfquery name="getColumn" datasource="mydatasource">
        <!--- I'm trying to use cfqueryparam to add specify the column name to select. --->
        SELECT <cfqueryparam cfsqltype="cf_sql_varchar" maxlength="50" value='#columnName#'>
        FROM table_name
        WHERE (accountName = <cfqueryparam cfsqltype="cf_sql_varchar" maxlength="50" value='#accountName#'>)
    </cfquery>

    <!--- This line doesn't work. --->
    <cfreturn getColumn[#columnName#] >

</cffunction>

我认为您可以在括号符号中使用变量,例如getColumn[#columnName#]或者getColumn[columnName]因为有人在评论中提到它。但是当我自己尝试使用变量时,它并没有按预期工作。我收到此错误:

The value returned from the getColumnValueFromAccount function is not of type string. If the component name is specified as a return type, it is possible that either a definition file for the component cannot be found or is not accessible.

知道当我想获得 cfquery 的单个结果时应该采取什么路线,但我没有在查询的 SELECT 部分使用硬编码的列名吗?通常这个过程很简单,但是当你的列名是一个变量时,情况似乎有点不同。

4

2 回答 2

3

查询是数组的结构,如 queryname[key][1]。

由于向后兼容性,它首先可以工作。从一开始你可以做 queryname.columnname 和 CF 将输出该列查询的第一行。一旦切换到对象语法,它就不再那样工作了。

在你的 cfreturn 中试试这个:

getColumn[columnName][1]

注意 - 您的 cfreturn 示例中不需要井号。

于 2016-04-07T19:31:12.610 回答
1

我的解决方案:

根据 Leigh 的建议,我不能cfqueryparam以我尝试使用它的方式使用它,以及 Mark A Kruger 的回答,我能够修改我的代码并让它工作。现在看起来像这样:

<cffunction name="getColumnValueFromAccount" access="public" returntype="string" >
    <cfargument name="accountName" type="string" required="yes" />
    <cfargument name="columnName" type="string" required="yes" />

    <cfquery name="getColumn" datasource="mydatasource">
        SELECT #columnName#
        FROM table_name
        WHERE (accountName = <cfqueryparam cfsqltype="cf_sql_varchar" maxlength="50" value='#accountName#'>)
    </cfquery>

    <cfreturn getColumn[columnName][1] >

</cffunction>

它现在正确地返回指定系统中的帐户角色,即如果帐户accountNameadmininExampleSystem并且我传递role_ExampleSystem给函数,因为ColumnName函数将按admin预期返回。

警告:如果使用不当,我的解决方案可能会带来 SQL 注入风险!

在这样的 SQL 语句中使用 ColdFusion 变量不会提供任何防止 SQL 注入的保护,因此允许用户输入用于此处的数据将是一个非常糟糕的主意。columnName在我的情况下,这个函数只会被我编写的其他服务器端函数调用,并且正在使用的数据columnName将被硬编码在服务器端函数中。accountName另一方面, 是用户指定的,因此重要的是它位于cfqueryparam.

另一种更安全的解决方案:

Mark A Kruger提到,最好选择您可能需要的每一列,然后阅读您真正感兴趣的那一列。这似乎是个好主意。毕竟,获取记录的每个(相关)列不太可能是比我的单列示例更大的数据库调用——除非您的数据库具有包含大量列的大量记录。您也可以这样做,并且作为附带的好处,您不必担心#variable#在 a中使用常规冷融合cfquery可能会打开您的 SQL 注入。

阅读每个人的答案和评论非常有启发性。希望这个问题及其答案可以帮助其他有兴趣在 ColdFusion 中做类似事情的人!

于 2016-04-07T20:35:23.227 回答