2012-04-16 9 views
2

実際にはうまくいかないことがあります。CFC内でメソッドを呼び出すのに失敗しましたが、オブジェクトとして作成するとうまくいきます。

- save 
- create 
- update 

I保存方法にargumentCollectionを渡す:

IはCFC(guest.cfc)内の3つの方法を持っています。

saveGuest = objGuest.save(argumentcollection=guestStruct) 

それはIdentierが含まれている場合、それは、それが作成したメソッドにコレクションを渡していない場合、それは、updateメソッドにargumentCollecionを渡します。

これは、アプリケーションの1か所から呼び出されたときに問題なく動作しますが、saveメソッドへの新しい呼び出しを作成すると、createメソッドはうまく動作しますが、updateメソッドでIDが渡されると、 UPDATE変数が存在しないというエラーです。

しかし、私は、CFCのオブジェクトを作成することによって、私はそれを呼び出す方法を変更した場合、それが動作する...

..だから

saveObject = update(argumentCollection = arguments; 

は動作しません。更新変数が存在しないというエラーを受け取ります。

saveObject = createObject("component",'guest').update(argumentCollection = arguments); 

が動作します。

これらの呼び出しは両方ともguest.cfc内で発生していることに注意してください。

この問題は、フォーム構造体を保存メソッドに渡すときには発生しませんが、標準構造体(XMLインポートから構築)を渡すと発生します。

非常に奇妙です。

これを引き起こす可能性のあることは誰でも知っていますか?


EDIT 4月24日 - 追加されたコードguest.cfcため


<cffunction name="save" output="false" access="remote" hint="save guest"> 
    <cfargument name="title" type="any" required="false" default="" /> 
    <cfargument name="first_name" type="any" required="false" default="" /> 
    <cfargument name="surname" type="any" required="false" default="" /> 
    <cfargument name="dob" type="any" required="false" default="NULL" /> 
    <cfargument name="partner_first_name" type="any" required="false" default="" /> 
    <cfargument name="partner_surname" type="any" required="false" default="" /> 
    <cfargument name="partner_dob" type="any" required="false" default="NULL" /> 
    <cfargument name="address_1" type="any" required="false" default="" /> 
    <cfargument name="address_2" type="any" required="false" default="" /> 
    <cfargument name="address_3" type="any" required="false" default="" /> 
    <cfargument name="city" type="any" required="false" default="" /> 
    <cfargument name="state" type="any" required="false" default="" /> 
    <cfargument name="postcode" type="any" required="false" default="" /> 
    <cfargument name="country" type="any" required="false" default="" /> 
    <cfargument name="phone_bh" type="any" required="false" default="" /> 
    <cfargument name="phone_ah" type="any" required="false" default="" /> 
    <cfargument name="phone_mob" type="any" required="false" default="" /> 
    <cfargument name="fax" type="any" required="false" default="" /> 
    <cfargument name="email" type="any" required="false" default="" /> 
    <cfargument name="business" type="any" required="false" default="" /> 
    <cfargument name="notes" type="any" required="false" default="" /> 
    <cfargument name="referer" type="any" required="false" default="" /> 
    <cfargument name="prospect" type="any" required="false" default="" /> 
    <cfargument name="occasion" type="any" required="false" default="" /> 
    <cfargument name="occasion_date" type="any" required="false" default="NULL" /> 


    <!---pass to Create or Save---> 
    <cfif NOT isdefined("arguments.guest_id") OR arguments.guest_id EQ "0"> 
     <cfset saveObject = create(argumentCollection = arguments) /> 
    <cfelse> 
     <cfset saveObject = update(argumentCollection = arguments) /> 
    </cfif> 

    <cfreturn saveObject> 

</cffunction> 


<!---CREATE---> 
<cffunction name="create" output="false" access="private" returntype="struct" hint="Create a New Item"> 
    <cfargument name="provider_id" type="any" required="false" default="#session.providerID#" /> 
    <cfargument name="ext_ref_id" type="any" required="false" default="NULL" /> 
    <cfargument name="tstamp" type="any" required="false" default="#session.tStamp#" /> 

    <cfif isValid('date',arguments.occasion_date)> 
     <cfset iOccasionDate = createODBCDateTime(arguments.occasion_date)> 
    <cfelse> 
     <cfset iOccasionDate = "NULL"> 
    </cfif> 

    <cfset returnStruct = StructNew()> 

    <cfquery name="insertGuest" datasource="#Application.ds#"> 
     INSERT INTO guest (provider_id, ext_ref_id, title, first_name, surname, full_name, partner_first_name, partner_surname, partner_full_name, address_1, address_2, address_3, city, state, postcode, country, phone_bh, phone_ah, phone_mob, fax, email, company, notes, referer, prospect, occasion, occasion_date, tstamp) 
     VALUES (#provider_id#, #ext_ref_id#, '#arguments.title#', '#arguments.first_name#', '#arguments.surname#', '#arguments.first_name# #arguments.surname#', '#arguments.partner_first_name#', '#arguments.partner_surname#', '#arguments.partner_first_name# #arguments.partner_surname#', '#arguments.address_1#', '#arguments.address_2#', '#arguments.address_3#', '#arguments.city#', '#arguments.state#', '#arguments.postcode#', '#arguments.country#', '#arguments.phone_bh#', '#arguments.phone_ah#', '#arguments.phone_mob#', '#arguments.fax#', '#arguments.email#', '#arguments.company#', '#arguments.notes#', '#arguments.referer#', '#arguments.prospect#', '#arguments.occasion#', #iOccasionDate#, #CreateODBCDateTime(tstamp)#) 
    </cfquery> 

    <cfquery name="guest" datasource="#Application.ds#"> 
     SELECT max(guest_id) as id 
     FROM guest 
     WHERE provider_id = #provider_id# 
    </cfquery> 

    <cfset returnStruct.id = #guest.id#> 
    <cfreturn returnStruct> 

</cffunction> 



<!---UPDATE---> 
<cffunction name="update" output="false" access="private" returntype="struct" hint="Update an existing item"> 

    <!---general details---> 
    <cfquery name="update" datasource="#Application.ds#"> 
     UPDATE guest 
     SET provider_id = provider_id 

      <cfif isdefined("arguments.title")> 
       ,title = '#arguments.title#' 
      </cfif> 
      <cfif isdefined("arguments.first_name")> 
       ,first_name = '#arguments.first_name#' 
      </cfif> 
      <cfif isdefined("arguments.surname")> 
       ,surname = '#arguments.surname#' 
      </cfif> 
      <cfif isdefined("arguments.full_name")> 
       ,full_name = '#arguments.full_name#' 
      </cfif> 
      <cfif isdefined("arguments.dob")> 
       ,dob = #formDate2odbcDate(arguments.dob)# 
      </cfif> 

      <cfif isdefined("arguments.partner_first_name")> 
       ,partner_first_name = '#arguments.partner_first_name#' 
      </cfif> 
      <cfif isdefined("arguments.partner_surname")> 
       ,partner_surname = '#arguments.partner_surname#' 
      </cfif> 
      <cfif isdefined("arguments.partner_full_name")> 
       ,partner_full_name = '#arguments.partner_full_name#' 
      </cfif> 
      <cfif isdefined("arguments.partner_dob")> 
       ,partner_dob = #formDate2odbcDate(arguments.partner_dob)# 
      </cfif> 

      <cfif isdefined("arguments.address_1")> 
       ,address_1 = '#arguments.address_1#' 
      </cfif> 
      <cfif isdefined("arguments.address_2")> 
       ,address_2 = '#arguments.address_2#' 
      </cfif> 
      <cfif isdefined("arguments.address_3")> 
       ,address_3 = '#arguments.address_3#' 
      </cfif> 
      <cfif isdefined("arguments.city")> 
       ,city = '#arguments.city#' 
      </cfif> 
      <cfif isdefined("arguments.state")> 
       ,state = '#arguments.state#' 
      </cfif> 
      <cfif isdefined("arguments.postcode")> 
       ,postcode = '#arguments.postcode#' 
      </cfif> 
      <cfif isdefined("arguments.country")> 
       ,country = '#arguments.country#' 
      </cfif> 
      <cfif isdefined("arguments.phone_bh")> 
       ,phone_bh = '#arguments.phone_bh#' 
      </cfif> 
      <cfif isdefined("arguments.phone_ah")> 
       ,phone_ah = '#arguments.phone_ah#' 
      </cfif> 
      <cfif isdefined("arguments.phone_mob")> 
       ,phone_mob = '#arguments.phone_mob#' 
      </cfif> 
      <cfif isdefined("arguments.fax")> 
       ,fax = '#arguments.fax#' 
      </cfif> 
      <cfif isdefined("arguments.email")> 
       ,email = '#arguments.email#' 
      </cfif> 
      <cfif isdefined("arguments.subscribe_email_broadcast")> 
       ,subscribe_email_broadcast = '#arguments.subscribe_email_broadcast#' 
      </cfif> 
      <cfif isdefined("arguments.company")> 
       ,company = '#arguments.company#' 
      </cfif> 
      <cfif isdefined("arguments.notes")> 
       ,notes = '#arguments.notes#' 
      </cfif> 
      <cfif isdefined("arguments.prospect")> 
       ,prospect = '#arguments.prospect#' 
      </cfif> 
      <cfif isdefined("arguments.occasion")> 
       ,occasion = '#arguments.occasion#' 
      </cfif> 
      <cfif isdefined("arguments.occasion_date")> 
       ,occasion_date = #formDate2odbcDate(arguments.occasion_date)# 
      </cfif> 

     WHERE guest_id = #arguments.guest_id# 
    </cfquery> 

    <cfset returnStruct = structNew()> 
    <cfset returnStruct.id = arguments.guest_id> 
    <cfreturn returnStruct> 

</cffunction> 

+1

ジェイソン:guest.cfcコードを投稿できますか?もう少し見ることなくここで遊ぶことができるかもしれないことを伝えるのはちょっと難しい(少なくとも私にとって:)。ありがとう! –

+0

'saveObject = update(argumentCollection = arguments;')に括弧がありません – ale

+0

可能であれば、コードを投稿してください。 – jfrobishow

答えて

2

あなたは彼らが関数のローカル変数のスコープ内に作成されることを保証するために<cfset var iOccasionDate = ... >または<cfset local.iOccasionDate = ... >または<cfquery name="local.insertGuest" ...>のいずれかを記述すること、および他の変数を上書きしない必要があります。ですから、更新クエリを使用して更新機能を上書きしている

<cfquery name="update" datasource="#Application.ds#"> 

:あなたがこれを持っているので


あなたの具体的な問題があります。


注意すべきいくつかの簡単なもの:

  • ローカルスコープはCF9にし、上記の動作します。あなたがCF8以下であれば、関数の先頭に<cfset var local = StructNew() />と書くことで模倣する必要があります。

  • あなたが使用している場合はRailoまたはOpenBDが常に(VAR /ローカルスコープの必要性を回避する)ローカルスコープ内に作成するデフォルトの動作を変更するための設定がありますが、ACFは、このオプションがありません(まだ?)

  • cfqueryparamを使用してください! - サイモンはすでにこれについて言及していますが、繰り返すには十分に重要です。 常には、意図的および意図しないインジェクション攻撃を防止するために、またcfqueryのためにcfqueryparamを使用することに基づいて、データが使用される場所に基づいてデータを処理します。

+0

+1は "更新"を上書きしていることに気づいていませんでした - これがコードレビューで私がスコープに非常に厳しい理由です! –

+0

ピーター、これは明らかでした。ありがとうございました!! – Jason

2

これは、CFCのコードのサンプルとすることなく、より正確には少し難しいですしかし、私はあなたのコンポーネントのinit()をチェックすることを提案する傾向があります。 init()メソッドがありますか?それを呼び出していますか?例えば、コンポーネント定義

<cfcomponent> 

    <cffunction name="init" access="public"> 
     <cfreturn this> 
    </cffunction> 

    <cffunction name="save" access="public"> 
     <!--- logic ---> 
    </cffunction> 

    <cffunction name="create" access="public"> 
     <!--- logic ---> 
    </cffunction> 

    <cffunction name="update" access="public"> 
     <!--- logic ---> 
    </cffunction> 

</cfcomponent> 

の概要これは、CFCが厄介であるあなたの例

を、次の次

<cfscript> 
    // This will work in CF9 upwards 
    objCFC = new guest(/* add any arguments you have in the init() method here */); 
    objCFC.update(......); 

    // This also works 
    objCFC = CreateObject('component','guest').init(/* add any arguments you have in the init() method here */); 
    objCFC.update(......); 
</cfscript> 

編集のいずれかによって呼び出されます。さまざまな目立つ問題があります。

  1. CFC内のアプリケーション/セッションスコープに依存しているため、グローバル変数に依存しています。これはinit(datasource, provider_id, ext_ref_id, tstamp)のようにinit()メソッドが使用され、variables.スコープに格納されるため、CFCの外で定義されていない変数に対して脆弱ではなくなります。
  2. VARCHARフィールドは、リモートアクセスが許可されたcfcでエスケープされます。これはSQLインジェクションに対して非常に脆弱です。 Mr Bobby Tablesは、これがなぜ悪いのかを示すことができます(http://bobby-tables.com/
  3. 文字列値NULLを使用し続けます。これをvarchar/quotes内のデータベースに渡すと、データベースのNULL値ではなくNULLとして格納されます。

すべての場合、このコンポーネントを書き直すのが最善の方法です。コンポーネントを使用するもののコード変更は、init()で追加する必要がある点まで最小限に抑えられますが、いくつかの引数を削除すると、安定性が向上し、この奇妙な問題はすべて消えてしまいます。関数の内部で、あなたはそのCFC /テンプレートのグローバル変数のスコープでこれらを作成している<cfset iOccasionDate = ... ><cfquery name="insertGuest" ...>のようなものを書くCFでは、

+0

Simon、ありがとう..いいえ、init()メソッドはありません。私は呼び出し時にオブジェクトを初期化しますが、これらのcfcはかなり古く、一般的には何年も信頼できるようにする必要があります。あまりにも編集しすぎることはあまりありません。 initメソッドを使用しても問題が発生していないと思いますか?遊びに値するかもしれません。再度、感謝します! – Jason

+1

まず、cfqueryparam。 http://bobby-tables.com/ - あなたのフロンティアについて、いくつかの詳細http://forums.adobe.com/thread/434078 –

+0

_「それを編集するのがやや気にしない」_なぜあなたは嫌いですか?あなたは常にソース管理の古いバージョンを持っています。そして、テストスイートを展開する前に実行して、それらがまだ同じ機能を果たしていることを確認してください。心配する必要はありません。 –

関連する問題