将cfqueryparam与自定义标签一起使用?使用自定义标记嵌套本机标记

时间:2014-10-30 14:00:51

标签: coldfusion nested cfquery custom-tags cfqueryparam

我基本上想要允许这样的内容:

<cf_datatables datasource="#someDS#">

    <cf_datatables_records>

        SELECT
            `someColumn1`,
            `someColumn2`

        FROM
            `#someDB#`.`#someT#`

        WHERE
            `someColumn1` = <cfqueryparam value="#someValue#"  cfSqlType="CF_SQL_INTEGER">

        LIMIT
            10

    </cf_datatables_records>

</cf_datatables>

cf_datatables_records自定义标记(子)是将在cf_datatables自定义标记(父级)中使用的子查询/记录集。这将是执行上述操作时的SQL结果:

SELECT
    SQL_CALC_FOUND_ROWS *

FROM (

        SELECT
            `someColumn1`,
            `someColumn2`

        FROM
            `#someDB#`.`#someT#`

        WHERE
            `someColumn1` = <cfqueryparam value="#someValue#"  cfSqlType="CF_SQL_INTEGER">

        LIMIT
            10

) AS `base`

UNION (...)

WHERE ... GROUP BY ... ORDER BY ... LIMIT ... etc. (depends on the provided parameters)

不幸的是,ColdFusion在将cfqueryparam标记传递给自定义标记之前对其进行解析,从而导致:

Context validation error for tag cfqueryparam. The tag must be nested inside a cfquery tag.

如果省略cfqueryparam,它确实有效,但这显然是不可接受的。解析queryparam也是如此。

知道如何解决这个问题吗?

3 个答案:

答案 0 :(得分:0)

好的,我发现我可以在cfquery中包含SQL指令而不处理本机标记问题。

<cfquery datasource="#someDS#">

    <!--- count possible records --->
    <cfmodule dtArguments="#dtController.params#" template="datatables-processing-pre.cfm">

        <!--- select records for the desired entity --->
        SELECT
            `someColumn1`,
            `someColumn2`

        FROM
            `#someDB#`.`#someT#`

        WHERE
            `someColumn1` = <cfqueryparam value="#someValue#"  cfSqlType="CF_SQL_INTEGER">

        LIMIT
            10

    <!--- filter, order and paginate records --->
    <cfmodule dtArguments="#dtController.params#" template="datatables-processing-post.cfm">

</cfquery>

这两个包括动态补充选择。

datatables-processing-pre.cfm的内容:

SELECT
    SQL_CALC_FOUND_ROWS *

FROM (

datatables-processing-post.cfm的内容:

) AS 'base'

WHERE
    <cfswitch ...>
        <defaultcase>
            `someColumn3` > <cfqueryparam value="#someOtherValue#"  cfSqlType="CF_SQL_INTEGER">
        </defaultcase>
    </cfswitch>

    <cfif ...>
        AND `someColumn4` LIKE <cfqueryparam value="#anotherValue#%"  cfSqlType="CF_SQL_VARCHAR">
    </cfif>

ORDER BY
    <cfswitch ...>
        ...
    </cfswitch>

...

答案 1 :(得分:0)

问题是可以解决的,但可能不像你希望的那么容易。

您必须创建一个标签(或其他类似标签)来替换您的标签。其中每个都必须输出一个您可以使用的字符串(可能与标记提供给其父项的一些数据结合使用),以便稍后在父标记的结束模式中使用一些循环和字符串替换来重新创建cfqueryparam标记。

如果您想查看其中的示例,请查看我的Neptune框架的自定义标记中的cf_DMQuery和cf_DMSQL标记。

https://github.com/sebtools/Neptune

您可以在&#34; CustomTags&#34;中找到它们。存储库的文件夹。问题的关键在DMUdfs.cfm中的convertSQLArray函数中得到解决。它利用DataMgr.cfc中的功能来处理高度动态的SQL代码。

总而言之,它可以完成,但希望花一些时间。

由于Mark Kruger(我尊敬和敬佩)认为这样的标签只能让你获得开销,我会补充一点,这样的自定义标签可以带来真正的好处。我已经看到了一些标签,包括在数据库连接断开导致失败的情况下重试整个查询调用(可能是另一个数据库)的能力。

我已经使用过它们,因此我可以在多个不同的查询中使用复杂的SQL(包括cfqueryparams)。我获得了在SQL中执行复杂逻辑的速度优势,而无需代码重复的代价。然而,很难发布一个这样的例子,因为你的情况必须达到一定程度的复杂性才能得到回报(这使得很难得出一个简洁的例子)。

答案 2 :(得分:-1)

为什么不在执行查询之前添加检查以查看值是否为正确类型,而不是cfqueryparam?

<cfif NOT IsNumeric(somevalue)>
  <cfabort>
</cfif>

编辑:对整数也有类型检查:IsValid(“integer”,somevalue);

同意,它并不比使用cfqueryparam好,但根据使用情况可能没问题。