【问题标题】:In ColdFusion, how can I extract and store the contents of the submitted form?在 ColdFusion 中,如何提取和存储提交表单的内容?
【发布时间】:2009-02-03 07:21:59
【问题描述】:

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

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

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

例如,如果:

form.abc = 1
form.def = 2

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

this document on looping over a structure 是否在正确的路径上?

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

【问题讨论】:

    标签: database coldfusion error-logging


    【解决方案1】:

    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 方面需要任何帮助。


    希望这会有所帮助。 :)

    【讨论】:

    • 噢!我知道那里似乎有些不对劲。感谢您更正 FieldNames - ColumnList 是查询使用的内容。
    【解决方案2】:

    如果您想手动遍历所有表单字段,最简单的方法是像这样的 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">
    

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

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

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

    【讨论】:

    • 从来没有听说过 BugLogHQ,但它看起来是一个不错的应用程序,并且根据需要集成/扩展并不困难。 *** 我认为您应该编辑/拆分您的答案以使其更清晰。
    • 重写得更清晰、信息更丰富、内容更全面。 :)
    • 是的,BugLogHQ 非常好。你可以在这里阅读它的经验 - obligious.blogspot.com/2011/12/…
    【解决方案3】:

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

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

    将数据放入数据库?你如何做到这一点取决于你以后想用它做什么。最灵活的解决方案可能是将整个 form(和 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>
    

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

    【讨论】:

    • WDDX 是一种非常“繁重”的数据格式 - 对于简单的表单/错误详细信息,它可能没问题,但我仍然建议使用更轻量级的格式(如 JSON 或 INI 样式)。
    【解决方案4】:

    如果您在应用程序中使用 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>
    

    【讨论】:

      【解决方案5】:

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

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

      您可以在其中倾倒任何您喜欢的范围。你可能需要也可能不需要我提供的。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-06-06
        • 1970-01-01
        • 1970-01-01
        • 2014-10-31
        • 2017-01-20
        • 2013-06-22
        • 1970-01-01
        相关资源
        最近更新 更多