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:21:23 ` : _ _ : <cfif key eq "#arguments.structstring#">
20

: <cfset y = evaluate(0,key) />
22

私は何を間違っているのですか、または私がやろうとしていることを達成するためのより良い方法がありますか(テーブルにデータベースコンテンツを表示し、同じテーブルを介してデータベースコンテンツを更新(更新および削除)します)

4

2 に答える 2

7

投稿したエラー メッセージは、評価機能を誤用していることを示しています。ドキュメントによると、次のように機能します。

1 つ以上の文字列式を左から右に動的に評価します。(左側の評価の結果は、右側の式で意味を持つことができます。) 右端の式を評価した結果を返します。

しかし、他にも問題があります。まず第一に、コードを 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)

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. の使用を次のものに置き換えますevaluatey = variables.instance.form[key]

問題が解決することを願っています...

機能するようになったら、変数名について考え始めます。「配列」は、実質的に CFML の予約語であるため、ひどい変数名です。また、「x」と「y」の使用はまったく説明的ではありません。この種の問題が、この質問への回答を難しくしている原因です。

于 2009-06-30T14:07:12.207 に答える
3

Adam Tuttle の投稿に完全に同意します。彼を支持して、私の答えの「解決策の部分」の部分を削除しました。したがって、「一般的な部分」に関する私の2セントは次のとおりです。

完全に回避Evaluate()することが、あなたができる最善のことです。コードの断片を実際に評価する以外に、これを使用する理由はありません(これは、避けるべきもう 1 つの問題です)。それがあなたがしていることではない場合、より適切な方法で解決できない状況はありません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 を記述しているわけではありません (ただし、これは好みの問題です)。
于 2009-06-30T15:24:21.677 に答える