ColdFusion цикл через структуру с ключом оценки не удается! Что мне не хватает? - PullRequest
2 голосов
/ 30 июня 2009

У меня есть этот код в моем 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#"><br> 20:
21 : <cfset y = evaluate(0,key) /><br> 22:
23 `:

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

Ответы [ 2 ]

7 голосов
/ 30 июня 2009

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

3 голосов
/ 30 июня 2009

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

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

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

невероятно равно:

<cfset foo = FORM[foo]>

Все злоупотребления «удобством» в Evaluate() можно устранить следующим образом.

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

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