4

我正在用 ColdFusion 编写一个应用程序,尽管它基本上是稳定的,但它时常出错。因为它已经取代了旧的应用程序,所以有时是用户而不是我得到错误。

我创建了一个很好的页面,当人们收到向我发送信息的错误时会得到该页面,例如错误、引荐来源、哪个页面上的错误、行号等。

我似乎无法工作的唯一一件事是获取提交的表单数据(如果有的话)。我不知道它事先在哪个页面出错,所以我不能只输出'#form.field#'。

例如,如果:

form.abc = 1
form.def = 2

如何在事先不知道它们的情况下从“表单”中获取变量名称和值?

这份文件是否在沿着正确路径的某处循环结构?

另外,我正在寻找一种将数据存储在数据库中的好方法,因为这是存储有关错误的其他信息的地方,我真的不想把它放在给我的电子邮件中。

4

5 回答 5

7

Form 范围有一个FieldNames变量,它将告诉您提交了哪些字段。

您还可以StructKeyList(Form)获取范围内当前变量的列表。这还将包括 FieldNames 和任何其他已添加到 Form 范围的变量。

这些中的任何一个都可以在内部使用<cfloop index="CurField" list="#StructKeyList(Form)#">- 但有更简单的方法......


如果您在 CF8 上,您可以使用serializeJson()deserializeJson()函数轻松地将范围转换为字符串,然后可以将其存储在合适的数据库字段中。

如果您使用的是 CF6..7,那么您可以从riaforge下载一个名为cfjson的 CFC,它模仿了这些功能。


最后,如果您使用的是早期版本的 CF,或者对使用 JSON 进行存储有一种奇怪的反感,您可以使用更简单的循环来滚动自己的循环到上面提示的循环 - 收集循环允许您直接循环遍历结构或范围 - 请注意,有些烦人的人选择了“项目”而不是“索引”作为这些属性。

因为我们知道表单变量都是简单的对象(即字符串),所以我选择了一种基本key=value[newline]key=value[newline]...格式,它也很容易反转。

编码:

<cfset Output = '' />
<cfloop item="CurField" collection="#Form#">
    <cfset Output = Output & CurField & '=' & Form[CurField] & Chr(10) />
</cfloop>

<cfoutput>#Output#</cfoutput>

解码:

<cfset FormData = StructNew()/>
<cfloop index="CurLine" list="#Output#" delimiters="#Chr(10)#">
    <cfset FormData[ListFirst(CurLine,'=')] = ListRest(CurLine,'=') />
</cfloop>

<cfdump var="#FormData#"/>


最后一个重要注意事项:与所有用户提供的变量(Form、Url、Cookie 范围)一样,您必须确保正确处理它们以防止安全漏洞 - 特别是确保您使用 cfqueryparam 进行 所有 数据库查询- 不想要偏离得太远了,但如果您需要有关 cfqueryparam 的任何帮助,请随时提出另一个问题。


希望这可以帮助。:)

于 2009-02-03T08:14:47.913 回答
4

如果您想手动遍历所有表单字段,最简单的方法是像这样的 cfloop:

<cfloop collection="#form#" item="variables.name">
  #variables.name#=(#form[variables.name]#)<br/>
</cfloop>

但话虽如此,出于错误电子邮件的目的,您可能会发现“转储”表单范围(这只是一个特殊结构)更容易,如下所示:

<cfmail
  from="errors@#cgi.server_name#"
  to="you@yourdomain.com"
  subject="Error Occurred in such and such a place"
  type="html">
    <cfdump var="#form#"/>
</cfmail>

在发送错误电子邮件时,我喜欢在 CGI 范围内包含第二个cfdump(同样,只是一个特殊的结构),因为这可以提供有关请求的其他一些有用信息。

如果您有 CF 8,您可能还想以文本格式转储,如下所示,因为它会使消息大小更小(在我看来,使消息更具可读性)

<cfdump var="#form#" format="text">

注意:formatCFDump 标签的属性是为 CF 8 添加的,因此您将无法在以前的 ColdFusion 版本中使用它。

您提到您正在寻找一种将这些错误存储在数据库中的方法,这是一个好主意。我建议您查看BugLogHQ ,而不是为此推出您自己的自定义解决方案。它已经存在了一段时间,对包括我在内的其他人都很好用,最重要的是它是免费和开源的。它的年龄和广泛使用意味着它自己的代码不太可能出现错误,并且可能具有比您编写的更多、更好的功能。

使用 BugLogHQ,您不必担心错误的显示,您只需将数据发送到错误记录器,剩下的就交给它了。

于 2009-02-05T13:33:12.900 回答
3

Form只是一个哈希/结构,所以你可以遍历它的键:

<cfoutput>
 <cfloop collection=#form# item="field">
  #htmleditformat(field)=#htmleditformat(form[field])#<br/>
 </cfloop>
</cfoutput>

将数据放入数据库?你如何做到这一点取决于你以后想用它做什么。最灵活的解决方案可能是将整个form(and url) 转换为 WDDX 对象,并将其存储在 blob 字段中:

<cfwddx action="cfml2wddx" input=#url# output="encodedURL"/>
<cfwddx action="cfml2wddx" input=#form# output="encodedForm"/>
<cfquery datasource="yourDSN">
 INSERT INTO errorlog (datestamp, event, script_name, path_info, url, form)
 VALUES
  (<cfqueryparam value=#now()# cfsqltype="CF_SQL_TIMESTANP"/>,
   <cfqueryparam value="your error string or cfcatch data" cfsqltype="CF_SQL_VARCHAR"/>,
   <cfqueryparam value=#cgi.script_name# cfsqltype="CF_SQL_VARCHAR"/>,
   <cfqueryparam value=#cgi.path_info# cfsqltype="CF_SQL_VARCHAR"/>,
   <cfqueryparam value=#encodedURL# cfsqltype="CF_SQL_BLOB"/>,
   <cfqueryparam value=#encodedForm# cfsqltype="CF_SQL_BLOB"/>)
</cfquery>

这样您就可以在闲暇时访问所有原始数据进行分析。当然,还有很多其他方法可以解决这个问题。

于 2009-02-03T08:47:54.023 回答
3

如果您在应用程序中使用 Application.cfc,只需将 onError 方法替换为下面的方法。注意:application.settings.mode 可以是以下值之一(dev、test、prod)。application.settings.webmasteremail 应设置为您希望将错误信息邮寄到的电子邮件地址。这两个变量都应该在 onApplicationStart 方法中设置。

这个函数有什么作用?如果应用程序设置为“dev”模式(通过设置 application.settings.mode = “dev”),它将在屏幕上显示错误信息。如果应用程序设置为任何其他模式(如测试或产品),它将通过电子邮件发送信息并将信息存储在数据库中。

<cffunction name="onError" returnType="void" output="true">
    <cfargument name="exception" required="true">
    <cfargument name="eventname" type="string" required="true">
    <!--- corrects bug where <cfabort> throw an error --->
    <cfif arguments.exception.rootCause eq "coldfusion.runtime.AbortException">
        <cfreturn>
    </cfif>
    <cfsavecontent variable="errordata">
        <p>#eventname#</p>
        <cfdump var="#exception#" label="Exception Information" format="text">
        <cfdump var="#url#" label="URL Information" format="text">
        <cfdump var="#form#" label="FORM Information" format="text">
        <cfdump var="#application#" label="Application Scope" format="text">
        <cfif isdefined("session")>
            <cfdump var="#session#" label="Session Scope" format="text">
        </cfif>
        <cfif isdefined("client")>
            <cfdump var="#client#" label="Client Scope" format="text">
        </cfif>
        <cfdump var="#cgi#" label="URL Information" format="text">
    </cfsavecontent>

    <!--- will email the error inforation and display the error page --->
    <cfif application.settings.mode eq "dev">
        <p>#eventname#</p>
        #errordata#
    <cfelse>
        <cfmail to="#application.settings.webmasteremail#" from="error@#cgi.http_host#" subject="Error has occured on #cgi.http_host#" type="HTML" charset="windows-1252">
        <p>#eventname#</p>
        #errordata#
        </cfmail>

        <cfquery datasource="yourDSN">
        insert into errorlog
        (
            creationdate
            ,event
            ,info
        )
        values
        (
            <cfqueryparam value="#now()#" cfsqltype="CF_SQL_TIMESTAMP"/>
            ,<cfqueryparam value="#eventname#" cfsqltype="CF_SQL_VARCHAR"/>
            ,<cfqueryparam value="#errordata#" cfsqltype="CF_SQL_LONGVARCHAR"/>
        )
        </cfquery>

        <h2>A functional error has occurred.</h2>
        <p>A notification of this error has been automatically e-mailed to the development team; no action on your part is required.</p>
        <p>Please click the "back" button on your browser to return to the web site.  We apologize for this inconvenience.</p>
    </cfif>
</cffunction>
于 2009-02-03T14:20:23.633 回答
0

如果您通过电子邮件向自己发送表单变量,只需转储它们,如下所示:

<cfmail type="html" ...>
    <cfdump var="#form#" label="form">
    <cfdump var="#cgi#" label="cgi">
    <cfdump var="#session#" label="session">
</cfmail>

你可以在那里倾倒你喜欢的任何范围。你可能需要也可能不需要我提供的那些。

您说您最初的问题是应用程序正在替换旧应用程序?您是否在部署的同一台服务器上进行开发?如果是这样,您可以为您的开发副本更改应用程序的名称 - 确保名称是唯一的以避免此问题(如果这是您的问题)。

于 2009-02-03T18:27:19.610 回答