Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Цикл ColdFusion через структуру с оценкой ключа завершается ошибкой! Что мне не хватает?

Автор вопроса: mrt181Ответов: 2

У меня есть этот код в моем cfm, который работает

<cfif not StructIsEmpty(form)>
 <cfset larray = user.getArray() />
 <cfloop collection="#form#" item="key">
  <cfif left(key,4) eq "UPD_">
   <cfset x = listLast(key,"_") />
   <cfset y = evaluate(0,key) />
   <cfloop index="j" from="1" to="#arrayLen(larray)#">
    <cfif (larray[j][1] eq x) and (larray[j][3] neq y)>
     <cfset larray[j][3] = y />
     <cfif not LSIsNumeric(larray[j][3])>
      <cfset larray[j][3] = "0" />
     </cfif>
     <cfset larray[j][4] = "update" />
    </cfif>
   </cfloop>
  </cfif>
 </cfloop>

 <cfloop collection="#form#" item="key">
  <cfif left(key,4) eq "DEL_">
   <cfset x = listLast(key,"_") />
   <cfloop index="k" from="1" to="#arrayLen(larray)#">
    <cfif larray[k][1] eq x>
     <cfset larray[k][4] = "delete" />
    </cfif>
   </cfloop>
  </cfif>
 </cfloop>

 <cfset user = createObject("component", "cfc.User").init(
    identifier = FormatBaseN(form.id,10),
    array = larray
    ) />
</cfif>

<form name="usform" method="POST">
<cfset array = user.getArray() />
<cfoutput>
<cfloop index="i" from="1" to="#arrayLen(array)#">
<table>
 <tr>
  <td><input type="text" name="upd_#array[i][1]#" maxlength="6" size="6" value="#array[i][3]#" /></td>
  <td><input type="checkbox" name="del_#array[i][1]#" /></td>
 </tr>
</table>
<input type="hidden" name="id" value="#user.getIdentifier()#" />
</cfoutput>
</form>

Я поместил его в cfc, чтобы разделить свою логику и свое мнение, и я пытаюсь сделать его более общим.

<cfcomponent name="ArrayManager" output="false">
 <cffunction name="init" hint="constructor" output="false" returntype="ArrayManager">
  <cfargument name="user" type="User" required="true" hint="User bean" />
  <cfargument name="form" type="Struct" required="true" />
  <cfset variables.instance.array = arguments.user.getArray() />
  <cfset variables.instance.form = arguments.form />
  <cfreturn this />
 </cffunction>

 <cffunction name="update" access="public" output="true" returntype="boolean">
  <cfargument name="structstring" type="String" required="true" />
  <cfargument name="seperator" type="String" required="true" />
  <cfset var x = "0" />
  <cfset var y = "0" />
  <cfloop collection="#variables.instance.form#" item="key">
   <cfif key eq "#arguments.structstring#">
    <cfset x = listLast(key,"#arguments.seperator#") />
    <cfset y = evaluate(0,key) />
    <cfloop index="j" from="1" to="#arrayLen(variables.instance.array)#">
     <cfif (variables.instance.array[j][1] eq x) and (variables.instance.array[j][3] neq y)>
      <cfset variables.instance.array[j][3] = y />
      <cfif not LSIsNumeric(variables.instance.array[j][3])>
       <cfset variables.instance.array[j][3] = "0" />
      </cfif>
  <cfset variables.instance.array[j][4] = "update" />
 </cfif>
</cfloop>
   </cfif>
  </cfloop>
  <cfset arguments.user.init(array = variables.instance.array) />
  <cfreturn true />
 </cffunction>

 <cffunction name="delete" access="public" output="false" returntype="boolean">
  <cfargument name="structstring" type="String" required="true" />
  <cfargument name="seperator" type="String" required="true" />
  <cfset var x = "0" />
   <cfloop collection="#variables.instance.form#" item="key">
    <cfif key eq "#arguments.structstring#">
     <cfset x = listLast(key,"#arguments.seperator#") />
     <cfloop index="k" from="1" to="#arrayLen(variables.instance.array)#">
      <cfif variables.instance.array[k][1] eq x>
       <cfset variables.instance.array[k][4] = "delete" />
      </cfif>
     </cfloop>
    </cfif>
   </cfloop>
  <cfset arguments.user.init(array = variables.instance.array) />
  <cfreturn true />
 </cffunction>
</cfcomponent>

и мой новый cfm

<cfif not StructIsEmpty(form)>
 <cfset arraymanager = createObject("component","cfc.ArrayManager").init(user,form) />
 <cfset seperator = "_" />
 <cfset structstring = "UPD" />
 <cfset arraymanager.update(structstring,seperator) />
</cfif>
...

Это не удается, я получаю это сообщение об ошибке

Компилятор CFML обнаружил неожиданное исключение coldfusion.compiler.CompilerInternalException. Причиной этого было: Невозможно завершить перевод CFML на Java. Произошло в:

. . .

Ошибка произошла в C:\path\to\document\root\cfc\ArrayManager.cfc: строка 21
Вызывается из C:\path\to\document\root\cfc\update-emp.cfm: строка 66 Вызывается из C:\C:\path\to\document\root\cfc\update-emp.cfm: строка 66

19 : <cfif key eq "#arguments.structstring#">
20
:
21 : <cfset y = evaluate(0,key) />
22
:
23 `:

Что я делаю неправильно или есть лучший способ выполнить то, что я пытаюсь сделать (отображение содержимого базы данных в таблице и обновление (обновление и удаление) содержимого базы данных через ту же таблицу)

  • Я уже некоторое время пытался обдумать ваш код. Я понятия не имею, как экстраполировать недостающие биты. С какой структурой данных вы работаете? Как выглядит сообщение FORM? Почему вы помещаете все во вложенные массивы? Tomalak 30.06.2009
  • Я с Томалаком. Что ты пытаешься сделать? В частности, что вы ожидаете получить от ‹cfset y = Assessment(0,key) /› ? ale 30.06.2009
  • Я думаю, что это используется как способ сказать ‹cfif IsDefined(foo)›‹cfset x = foo›‹cfelse›‹cfset x = 0›‹/cfif› - но, честно говоря, я думаю, что это неубедительно по многим причинам. . Tomalak 30.06.2009

loopsdata-structuresevaluationcoldfusion

Ответы

Ответ 1 · рейтинг 7 · Adam Tuttle

Опубликованное вами сообщение об ошибке указывает на то, что вы неправильно используете функцию Evaluate. Согласно документам, это работает так:

Динамически оценивает одно или несколько строковых выражений слева направо. (Результаты вычисления слева могут иметь смысл в выражении справа.) Возвращает результат вычисления самого правого выражения.

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

В вашем рабочем коде вы используете условное выражение:

<cfif left(key,4) eq "UPD_">

Но в вашем CFC у вас есть:

<cfif key eq arguments.structString>

Это должно быть:

<cfif left(key,4) eq arguments.structString>

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

y = evaluate(0,key)

можно переписать как:

y = evaluate(key)

Поскольку значением ключа является "UPD_something", это можно переписать как:

y = [variables|arguments|etc].UPD_Something

(Поскольку вы явно не указываете область действия переменной, CF попытается найти переменную в наборе областей видимости в определенном порядке, поэтому я использовал синтаксис [a|b|...])

Вы, вероятно, не имеете в виду это, вы, вероятно, хотите получить значение из формы. И поскольку имя ключа является динамическим, вы должны обращаться к нему таким образом (вместо использования evaluate):

y = variables.instance.form[key]

Я думаю, это может исправить это. Итак, резюмируя:

  1. Замените оператор <cfif key eq arguments.structString> на <cfif left(key,4) eq arguments.structString> (и убедитесь, что значение, которое вы передаете как "structString", включает символ подчеркивания!)

  2. Замените использование evaluate на: y = variables.instance.form[key]

Надеюсь, это решит ваши проблемы...

После того, как вы заработаете, начните думать об именах ваших переменных. "Массив" - ужасное имя переменной, потому что это практически зарезервированное слово в CFML. А использование "x" и "y" вообще не описательно. Именно из-за этих типов проблем ответить на этот вопрос было трудно.

Ответ 2 · рейтинг 3 · Tomalak

Я полностью согласен с постом Адама Таттла. Я удалил часть своего ответа "часть решения" в пользу его. Итак, вот мои два цента относительно "общей части":

Лучше всего вообще избегать Evaluate(). Нет никакой причины использовать его, кроме фактической оценки фрагментов кода (что является еще одной неприятностью, которой следует избегать). Если это не то, что вы делаете, то нет такой ситуации, которую нельзя было бы разрешить с помощью чего-то более подходящего, чем Evaluate(), например:

<cfset foo = Evaluate("FORM.#foo#")>

равно:

<cfset foo = FORM[foo]>

Все "удобство" неправильного использования Evaluate() можно устранить таким образом.

Еще несколько советов:

  • Избегайте бессмысленных имен переменных, таких как "x" или "y" (если, конечно, вы не имеете в виду 2D-координаты).
  • Не делайте "#variable#" - вместо этого вы можете просто использовать variable.
  • Используйте структуры везде, где это возможно, когда вам нужно получить доступ к элементам с помощью ключа, например,
    <cfif array[i][1] eq SomeValue> намного менее элегантен, чем
    <cfif array[i]["FieldName"] eq SomeValue>
  • Вам действительно не нужно "variables.instance" - каждый экземпляр компонента имеет свою собственную область видимости VARIABLES. Все, что вы туда втыкаете, по умолчанию "только для экземпляра".
  • Нет необходимости передавать область FORM компоненту. Область действия глобальна, поэтому CFC все равно могут ее видеть.
  • Почему вы храните данные базы данных в дополнительном массиве вместо того, чтобы использовать объект Query, полученный при их извлечении?
  • Не нужно самостоятельно закрывать ("/>") операторы CFML - вы не пишете XML (хотя это дело вкуса).

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы