Как в ColdFusion извлечь и сохранить содержимое отправленной формы? - PullRequest
4 голосов
/ 03 февраля 2009

Я пишу приложение в ColdFusion, и хотя оно в основном стабильное, оно время от времени выдает ошибки. Поскольку оно уже заменило старое приложение, иногда именно пользователи получают ошибки вместо меня.

Я создал хорошую страницу, которую люди получают, когда получают сообщение об ошибке, присылающее мне информацию, такую ​​как ошибка, ссылка, ошибка на какой странице, номер строки и т. Д.

Единственное, что я не могу заставить работать, - это отправить данные формы, если они есть. Я не знаю, на какой странице она заблуждалась заранее, поэтому я не могу просто вывести '# form.field #'.

Например, если:

form.abc = 1
form.def = 2

Как я могу получить имена переменных и их значение из формы, не зная их заранее?

Является ли документом о циклическом перемещении по структуре где-нибудь по правильному пути?

Кроме того, я ищу хороший способ сохранить эти данные в базе данных, потому что именно там хранится другая информация об ошибке, и я не хочу помещать ее в электронное письмо на адрес я.

Ответы [ 5 ]

7 голосов
/ 03 февраля 2009

Область формы имеет переменную FieldNames, которая сообщит вам, какие поля были отправлены.

Вы также можете сделать StructKeyList(Form), чтобы получить список текущих переменных в области видимости. Этот также будет включать FieldNames и любые другие переменные, которые с тех пор были добавлены в область формы.

Любой из них можно использовать внутри <cfloop index="CurField" list="#StructKeyList(Form)#">, но есть более простые способы ...

1010 *
*

Если вы используете CF8, вы можете легко и просто преобразовать область в строку с помощью функций serializeJson() и deserializeJson(), которые затем можно сохранить в подходящем поле базы данных.

Если вы используете CF6..7, вы можете загрузить CFC с именем cfjson из riaforge , который имитирует эти функции.


Наконец, если вы работаете с более ранними версиями 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#"/>


Еще одно важное замечание: как и для всех пользовательских переменных (формы, URL-адреса, области cookie), вы должны убедиться, что обрабатываете их правильно, чтобы предотвратить дыры в безопасности - в частности, убедитесь, что вы используете cfqueryparam для все запросы к вашей базе данных - не хотите отвлекаться слишком далеко, но не стесняйтесь задавать другой вопрос, если вам нужна помощь с cfqueryparam.


Надеюсь, это поможет. :)

4 голосов
/ 05 февраля 2009

Если вы хотите вручную выполнить итерации по всем полям формы, самый простой способ - это 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>

При отправке электронных писем с сообщениями об ошибках мне нравится включать вторую cfdump для области CGI (опять же, просто специальную структуру), поскольку это может предоставить некоторую другую полезную информацию о запросе.

Если у вас CF 8, вам также может потребоваться сделать дамп в текстовом формате, как показано ниже, потому что это уменьшит размер сообщения (и, на мой взгляд, сделает сообщение более читабельным)

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

Примечание: атрибут format тега CFDump был добавлен для CF 8, поэтому вы не сможете использовать его в предыдущих версиях ColdFusion.

Вы упомянули, что искали способ сохранить эти ошибки в базе данных, и это хорошая идея. Вместо того, чтобы предлагать собственное решение для этого, я предлагаю вам проверить BugLogHQ . Это было вокруг некоторое время и хорошо работает для других, включая меня, и лучше всего это БЕСПЛАТНО и с открытым исходным кодом. Его возраст и повсеместное использование означают, что вероятность возникновения ошибок в собственном коде будет меньше, и, вероятно, у него будет больше возможностей, которые лучше, чем то, что вы написали бы.

Используя BugLogHQ, вам не нужно беспокоиться об отображении ошибки, вы просто отправляете данные в регистратор ошибок, а он позаботится обо всем остальном.

3 голосов
/ 03 февраля 2009

если вы используете 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>
3 голосов
/ 03 февраля 2009

Form - это просто хеш / структура, поэтому вы можете просто перебирать его ключи:

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

Поместить данные в базу данных? То, как вы это сделаете, зависит от того, что вы хотите с этим делать потом. Наиболее гибким решением может быть просто преобразовать все formurl) в объект 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>

Таким образом, вы будете иметь доступ ко всем исходным данным для анализа на досуге. Конечно, есть много других способов сделать это.

0 голосов
/ 03 февраля 2009

Если вы отправляете себе по электронной почте переменные формы, просто сбросьте их, например, так:

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

Вы можете выбрасывать там все, что вам нравится. Вы можете или не можете нуждаться в тех, кого я предоставил.

Вы сказали, что ваша первоначальная проблема заключалась в том, что приложение заменяет старое приложение? Вы разрабатываете на том же сервере, на котором развертываете? Если это так, вы можете просто изменить имя приложения для своей копии для разработки - убедитесь, что имена уникальны, чтобы избежать этой проблемы (если это и есть ваша проблема).

...