如何在一个CFC文件的查询中调用另一个CFC文件中的函数?

4

我有一个cfc文件(info.cfc),里面包含多个函数,如下所示。

<cfcomponent output="true" extends="DateFunctions">
    <cffunction name="getStatuses" access="remote" returntype="any" output="true" returnformat="plain">
       ...
    </cffunction>

    <cffunction name="viewDate" access="remote" returntype="any" output="true" returnformat="plain">
        <cfquery  name="records">
              SELECT
                 dbo.tickets.Incident,
                 dbo.tickets.Start_Date,
                 dbo.tickets.Days_Due
              FROM
                 dbo.tickets    
        </cfquery>
    </cffunction>
</component>

另一个cfc文件(DateFunctions.cfc)包含一个带有两个参数并返回日期的函数。 DateFunctions.cfc文件如下:

<cfcomponent output="true" name="DateFunctions"">
    <cffunction name="addBusinessDays" access="remote" returntype="any" output="true" returnformat="plain">
       <cfargument name="daysToAdd" 
                required="yes" 
                type="numeric" 
                hint="The number of whole business days to add or subtract from the given date">
        <cfargument name="date" 
                required="No" 
                type="date" 
                hint="The date object to start counting from.." 
                default="#NowDateTime#">

         ...
         ... <!--- Perform some tasks --->

         <cfreturn Date>
    </cffunction>
</cfcomponent>

问题:我如何在(info.cfc)的查询中调用“addBusinessDays”,同时生成另一列结果。
我认为我可以尝试以下方法:
<cffunction name="viewDate" access="remote" returntype="any" output="true" returnformat="plain">
    <cfquery  name="records">
          SELECT
             dbo.tickets.Incident,
             dbo.tickets.Start_Date,
             dbo.tickets.Days_Due,
             (
               <cfinvoke component="DateFunctions" method="addBusinessDays" returnVariable="Date">
                  <cfinvokeargument name="daysToAdd" value="#dbo.tickets.Days_Due#">
                  <cfinvokeargument name="date" value="#dbo.tickets.Start_Date#">
               </cfinvoke>
             ) AS Due_DATE
          FROM
             dbo.tickets    
    </cfquery>
</cffunction>

当HTML生成时,此处理应在视图页面上完成。 - Matt Busche
1
为了回答这个问题,我们需要看一下addBusinessDays的代码。 - Dan Bracuk
CFC不能以那种方式使用。ColdFusion服务器和数据库是完全独立的。CF对数据库对象一无所知,数据库也不知道CFML,因此您不能以这种方式混合两者。 ColdFusion的唯一工作是充当信使。在查询执行之前,它会进行其工作。CF评估任何cfml代码并将所有内容转换为文字。然后它构建一个SQL字符串并将该字符串发送到数据库以供执行。数据库完成其余工作。 - Leigh
另外,根据addBusinessDays的实际逻辑,您可以考虑将逻辑移至数据库,并使用a)带有JOIN的日历数据库表或b)标量数据库函数。 - Leigh
2个回答

1
您可以这样做,但循环会增加额外的处理。
编辑:根据下面的讨论,将cfoutput更新为cfloop。
 <cffunction name="viewDate" access="remote" returntype="any" output="true" returnformat="plain">
    <cfquery  name="records">
          SELECT
             dbo.tickets.Incident,
             dbo.tickets.Start_Date,
             dbo.tickets.Days_Due, 
            '' as Due_DATE
          FROM
             dbo.tickets    
    </cfquery>

    <cfset df = createobject("component","DateFunctions")>

    <cfloop query="records">
        <cfset records.Due_DATE = df.addBusinessDays(Days_Due, Start_Date)>
    </cfloop>

   <cfreturn records>
</cffunction>

1
  1. 不要忘记将所有函数局部变量(包括查询名称)设置为VAR/LOCAL范围
  2. 从CF循环中删除“dbo.tablename”。它不是查询列名的一部分
  3. 由于代码没有显示任何内容,使用cfloop而不是cfoutput
- Leigh
同时4)不要使用 '' as Due_DATE,因为它将无法生成新列的正确数据类型和/或大小。而是使用类似于 CAST(NULL AS datetime) AS Due_Date 的语句。确切的语法取决于DBMS。 - Leigh
1
在我看来:函数应该设置为 output="false",除非真的期望该函数生成输出。在我的代码中,更常见的情况是函数返回一个字符串而不是生成输出。这与以下内容有关:http://programmers.stackexchange.com/questions/187457/what-is-the-principle-of-least-astonishment - James A Mohler
1
@snackboy - 在文档中就有说明(https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-tags/tags-m-o/cfoutput.html): "显示输出...". 你说的是变量赋值,不是同一件事。回复:它确实保留查询列的数据类型吗? 呃? :) 这就是重点。查询列并非无类型。SQL 创建了一个带有错误数据类型的列。CFLoop 现在实际上支持分组。虽然对于旧版本来说,这是滥用 cfoutput 的少数合法用例之一。 - Leigh
1
@JamesAMohler - 同意,在不需要时抑制输出。我只是评论这种情况下不必要地使用cfoutput。文档已经改进了,但是仍然存在许多糟糕的例子,充满了过多的井号、引号和对cfoutput的误用;-)。不仅仅是例子是丑陋的代码,它们还会培养关于cfml某些方面的许多错误概念和误解,依我看来。 - Leigh
显示剩余7条评论

0

不要创建df对象,应该将其绑定到this作用域。这样对象只会被创建一次。这应该使viewDate函数运行更快,因为没有创建df的开销。

此外,new只是一种更清晰的语法。

<cfcomponent>

    <cfset this.df =  new DateFunctions()>

    <cffunction name="viewDate" access="remote" returntype="any" output="false" returnformat="plain">
        <cfquery  name="Local.records">
           SELECT
                dbo.tickets.Incident,
                dbo.tickets.Start_Date,
                dbo.tickets.Days_Due, 
                CAST(NULL AS datetime)
           FROM
                dbo.tickets    
       </cfquery>


      <cfloop query="Local.records">
         <cfset Local.records.Due_DATE = this.df.addBusinessDays( Local.records.Days_Due, Local.records.Start_Date)>
      </cfloop>

      <cfreturn Local.records>
    </cffunction>

<cfcomponent>

我意识到以上内容基于先前的答案,但是如评论中所提到的'' as Due_DATE 应该被替换为类似于 CAST(NULL AS datetime)(特定于dbms)以确保正确的列类型。 - Leigh
另请参见:https://dev59.com/DZfga4cB1Zd3GeqPDfQp - James A Mohler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接