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

У меня есть этот код в моем 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< br> Вызывается из 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 `:

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


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


Ответы (2)


Опубликованное вами сообщение об ошибке указывает на то, что вы неправильно используете функцию 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» вообще не описательно. Именно из-за этих типов проблем ответить на этот вопрос было трудно.

person Adam Tuttle    schedule 30.06.2009
comment
+1 Очень красиво. У меня было готово что-то подобное, но после того, как я стал неуверенным в том, что полностью понимаю цель исходного кода, я не решался опубликовать его. Пожалуй, я просто опубликую консультативную часть. - person Tomalak; 30.06.2009

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

Лучше всего вообще избегать 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 (хотя это дело вкуса).
person Tomalak    schedule 30.06.2009
comment
Я немного не согласен с передачей в области формы. Я считаю это частью отделения компонента от страницы, которая его использует. То же самое касается области приложения, области сеанса и т. д. (99% времени)... Как правило, вам не следует обращаться к ним напрямую из CFC. - person Adam Tuttle; 30.06.2009
comment
Я также являюсь поклонником тегов CFML в формате XML/XHTML, но, как вы сказали, это стилистический выбор, который должен сделать разработчик. Я считаю, что они делают более очевидным, когда тег в глубоко вложенной ситуации имеет или не имеет потомков; особенно полезно, когда IDE партнера мешает вашему отступу. - person Adam Tuttle; 30.06.2009
comment
Хм, я бы лично распял любого, кто напортачит с моим отступом. Но это опять дело вкуса. ;-) В любом случае, я действительно не вижу причин не использовать APPLICATION, SESSION и т. д. в CFC, если CFC является частью приложения (а не частью общего -целевой каркас). Я просто не люблю постоянно повторяться в аргументах cffunction. Какой веский аргумент против этого? - person Tomalak; 30.06.2009
comment
я храню данные базы данных в объектном компоненте, где я сохраняю больше, чем просто информацию о массиве. бессмысленные имена, где просто пример. Я согласен с Адамом, я думаю, что передача области формы компоненту делает более ясным, что компонент должен ее использовать. я вижу, что мне нужно многому научиться, программируя всего 4 недели. - person mrt181; 02.07.2009