多次将查询参数传递给 ColdFusion 文件?

3

我在一个名为 email_output.cfm 的文件中设置了一个 cfmail 函数,需要传递 ID 才能正常工作,如 email_output.cfm?ID=1。我想设置一个 cron job 通过查询返回所需的各个 ID。在测试中,我可以执行以下操作:

  <cflocation url="email_output.cfm?ID=10" >

但是,由于cflocation会停止所有其他执行并打开另一个页面,因此我无法循环遍历它。我该如何将参数从查询传递到单个CF页面多次?

谢谢 - 乔


1
这是一个自定义标签的理想函数。您可以通过调用 attributes.id 来代替 url.id。它也可以编写为 UDF。 - Regular Jo
我想我明白你关于使用自定义标签的意思,但不理解参数是如何传递的。它会像<cf_email_output Attributes.id="#rsIDs.ID">这样吗?一个具体的例子将会非常感激。 - Joe Lowery
请检查我刚刚添加的示例,确认我的答案是否正确。 - Regular Jo
2个回答

2

这是一个自定义标签的示例实现...

如果这是您第一次使用自定义标签,最简单的方法是将其放在调用它的页面相同的文件夹中。如果要将其放在不同的目录中,有几个选项可供选择,但我们先从简单的开始。

EmailMembers.cfm

<cfquery name="GetUIDs">
  select userid from users
</cfquery>

<cfoutput query="GetUIDs">
  <cf_maileach uid="#userID#">
</cfoutput>

请注意我如何称呼我的标签 cf_maileach?

在同一个目录中,放置 maileach.cfm 文件,看看它们的名称是否匹配?

maileach.cfm

<cfif StructKeyExists(attributes,"uid") and val(attributes.uid) gt 0>
  <cfquery name="getinfo">
    select fname,lname,email
      from users
     where userID = <cfqueryparam cfsqltype="cf_sql_integer" value="#attributes.uid#">
  </cfquery>

  <cfmail to="#getinfo.email#" subject="Hi #getinfo.fname#">...</cfmail>
</cfif>

注意事项:

  • 根据你使用的cf版本以及是否使用application.cfc文件,有几种方法可以将自定义标签放置在外部目录中。还有<cfmodule>
  • 这只是一个示例,这样基本的东西已经过时,我只是在模仿提问者所述的内容。在此示例中,我调用了一个可以获取所有数据的查询,仅使用它来逐行查询。
  • 如果你不熟悉<cfqueryparam>,请查找它、使用它并喜欢它。

编辑:虽然CFHTTP方法可以实现此目的,但它存在一些问题

  • 不会自动传递会话(即使请求服务器和目标服务器相同)。
  • 页面像浏览器请求一样访问。 应用程序/OnRequestEnd正在处理(由于会话信息也已传递,这可能导致尝试访问受保护区域中的文件时出现问题。
  • 由于上面的原因,该页面需要位于具有自己的Application文件的文件夹中,以消除目录层次结构中其上方的任何应用程序文件。
  • 为了解决1、2和3,您需要编写一层安全性,类似于您应用程序的自身安全性,以使文件不会在找到url时变得容易受攻击。
  • 每次通过cfhttp调用文件都需要调用一些额外的安全检查。
  • 它速度明显慢。 在一个没有内容的application.cfc上进行非常简单的测试中,自定义标记方法的执行时间真正达到了小于1/100。随着将实际功能添加到该方法中,结果的差异将发生变化。

以下是一些用于测试的示例代码。

文件夹“safe”的内容:

Application.cfc

[ blank file, to negate my testing site's actual application.cfc ]

Testrun.cfm

<cfoutput><cfset starttick = GetTickCount()>
<cfloop from="1" to="20" index="i">
  <cfhttp url="http://mysamesite.com/safe/http.cfm?u=#i#" method="get" result="test">
  #test.filecontent#<br>
</cfloop>
CFHTTP Execution Time: #(GetTickCount() - starttick)#<br><br>

<cfset starttick = GetTickCount()>
<cfloop from="1" to="20" index="i">
  <cf_testtag u="#i#"><br>
</cfloop>
CustomTag Execution Time: #(GetTickCount() - starttick)#<br><br>
</cfoutput>

testtag.cfm

<cfoutput>The ID entered was #attributes.u#</cfoutput>

http.cfm

<cfoutput>The ID entered was #url.u#</cfoutput>

结果(毫秒) 每个测试包括20次HTTP和20次自定义标记的通过。

CFHTTP  Tag
661ms   6ms
1624    5
616     5
460     4
522     6
816     4

实施您的解决方案后,我遇到了一个错误:`标记cfmail的属性验证错误。 当前属性查询的值为rsHeadCoach,无效。错误发生在D:\Inetpub\zzzz\admin\email\next-game-email-output.cfm:第102行100 : </cfscript> 101 : <cfmail 102 : query="rsHeadCoach" 103 : server="mail.zzzz.org" 104 : username="jlowery@zzzz.org"` FWIW,我传递的是字符串而不是整数,并将cfsqltype更改为cf_sql_varchar,值为“#attributes.uid#”。这可能是问题吗? - Joe Lowery
听起来 rsHeadCoach 在调用页面中,而不在自定义标签中?如果是这样,请尝试将您的 <cfmail> 更改为 <cfmail...query="caller.rsHeadCoach"...>caller scope 是您可以从调用页面访问变量的方式,而 Attributes 则是传递给标签的属性。 - Regular Jo
1
@JoeLowery Bracketsage不能为你编写代码,但他提供了一种可行的方法。请记住,在自定义标签中需要的每个变量(如果标签中没有已经编写或默认的)都需要作为属性传递到标签中(就像他在“ID”中所做的那样),或者从调用者范围中访问。因此,这种方法需要你进行一些编辑和重写。 - Mark A Kruger

2
你可以使用cfhttp来实现这一点。
 <cfquery name="GetUIDs">
    select userid from users
 </cfquery>

 <cfloop query="GetUIDs">
   <cfhttp url="http://localhost:8500/cf10/test.cfm?id=#userid#" method="get" result="test">
</cfloop>

虽然这可能符合您的实现,但它很懒。每个cfhtp都像一个浏览器请求。您需要/希望将其包含在自己的文件夹中,具有自己的application.cfc和自己的身份验证(也许模仿您网站的身份验证),以便如果有人发现它,它不会被自由暴露。最后,它要慢得多。请参见http://pastebin.com/FWXcRmDB,了解执行测试所需的代码以及我得到的结果。 - Regular Jo
那个二进制文件中有一个错别字,标签路由的结果从未超过8毫秒。我似乎在格式化时丢失了一条记录。 - Regular Jo

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