3

私は ColdFusion を初めて使用し、Ajax について学び始めたばかりです。私が持っている質問は、Web で 2 つのプルダウン メニューを実装するためのクールなコーディングを見つけたということです。ただし、目標は、選択クエリからプルダウン リスト内のすべての値を取得することです。

先ほど学んだバインド機能を使用しています。最初のプルダウンのすべてが正しくプルされています。しかし、問題は2つ目です。AJAX ロガーから取得しているエラーは、"Error invoking: Error Executing Database Query"アドバイスをいただければ幸いです。また、よろしくお願いいたします。

select.cfc

<cfcomponent output="false">

    <!--- Get array of Catagory Description types --->
    <cffunction name="cat_description" access="remote" returnType="array">

        <!--- Define variables --->
        <cfset var data="">
        <cfset var result=ArrayNew(2)>
        <cfset var i=0>

        <!--- Get data --->
        <cfquery name="getServiceCat" datasource="SOME_DATABASE">
            SELECT DISTINCT CAT_DESC
            FROM   service_table
            ORDER BY CAT_DESC
        </cfquery>

        <!--- Convert results to array---> 
        <cfloop index="i" from="1" to="#getServiceCat.recordcount#">
            <cfset result[i][1]=getServiceCat.CAT_DESC[i]>
            <cfset result[i][2]=getServiceCat.CAT_DESC[i]>
        </cfloop>

        <!--- And return it --->
        <cfreturn result>
    </cffunction>

    <!--- Get Service Type by Cat description type --->
    <cffunction name="getServiceType2" access="remote" returnType="array">
        <cfargument name="CAT_DESC" type="string" required="true">

        <!--- Define variables --->
        <cfset var data="">
        <cfset var result=ArrayNew(2)>
        <cfset var i=0>

        <!--- Get data --->
        <cfquery name="getServiceType2" datasource="SOME_DATABASE" dbtype="query">
            SELECT DISTINCT com_service_code, report_desc
            FROM   service_table
            WHERE  CAT_DESC = #ARGUMENTS.CAT_DESC# 
            ORDER BY report_desc
        </cfquery>
        </cfif>

        <!--- Convert results to array --->
        <cfloop index="i" from="1" to="#getServiceType2.recordcount#">
            <cfset result[i][1]=getServiceType2.com_service_code[i]>
            <cfset result[i][2]=getServiceType2.report_desc[i]>
        </cfloop>

        <!--- And return it --->
        <cfreturn result>
    </cffunction>

 </cfcomponent>

上記は、すべてのクエリを処理する cfc です。このソリューションの主な理由の 1 つは、フォーム内で必要なコードが単純であることです。

 ...
 <td>Select Category: <cfselect name="catdesc"
                                 bind="cfc:select.cat_description()"
                                 bindonload="true"/><br />
 </td>
 ...
 <td>Select Service:  <cfselect name="service"
                                bind="cfc:select.getServiceType2({catdesc})"
                                bindonload="false"/>
 </td>

クエリエラーの解決策を見つけるために、ほぼ2日間検索しました。クエリが SQL で機能することはわかっているので、問題は AJAX に関係しており、2 番目のプルダウンの WHERE 句が正しく実装されていないと考えています。

繰り返しますが、アドバイスや提案は素晴らしいでしょう。さらに、このソリューションを別の方法で行う場合は、それも試していただければ幸いです。私が述べたように、私はこの言語に非常に慣れていません。わずか2週間。

4

2 に答える 2

5

CFC のテスト

ajax にプラグインする前に、必ず CF で cfc をテストしてください。CFC がエラーなしで動作することを確認するまで、バインドをいじっても意味がありません。CF で動作しない場合は、ajax でも動作しないためです。唯一の違いは、エラーが見つけにくくなることです。

他の人が示唆したように、小さく始めてください。クエリを単独でテストします。次に、次の<cfinvoke>ようなテスト値を使用して CFC をテストするか、ブラウザから呼び出してCFC をテストします。

http://yourserver/path/to/select.cfc?method=getServiceType2&cat_desc= 
http://yourserver/path/to/select.cfc?method=getServiceType2&cat_desc=someValue

エラー

エラーに関しては、より具体的なアドバイスを提供するために完全なエラー メッセージを確認する必要があります。ただし、クエリ/コードを見ると、次のような原因が考えられます。

  1. CAT_DESCは varchar 列です。この場合、引数は一重引用符で囲む必要があります。そうしないと、データベースは引数の値がオブジェクト名 (テーブルまたは列) であると見なします。

    WHERE CAT_DESC = '#ARGUMENTS.CAT_DESC#' 
    
  2. .. ORCAT_DESCは数値列ですが、引数が空です。これにより、無効な sql ステートメントが生成されます。有効な数値がクエリに渡されるようにする必要があります (または、目的の結果に応じて、引数が空の場合は WHERE 句をスキップできます)。一般的なアプローチの 1 つは、val()関数を使用して空の文字列やその他の数値以外の値をゼロに変換することです。つまり、次のようになります。

    WHERE CAT_DESC = #val(ARGUMENTS.CAT_DESC)#

  3. </cfif>また、2番目のクエリの後に迷っているようです。(コピペミスじゃない前提で)

  4. もう1つ、2番目のクエリではdatasourceとの両方が指定されていますdbtype。これら 2 つの属性は相互に排他的です。両方を使用すると、構文エラーが発生する可能性があります (私は試していません)。いずれにせよ、そのうちの 1 つだけを使用する必要があります (ほとんどの場合datasource)。

SQL インジェクション

つまり、上記のクエリは sql インジェクションに対して脆弱です。<cfqueryparam>SQL インジェクションを防ぐために、常にすべての可変クエリ パラメータを使用する必要があります。他にもメリットがあります (パフォーマンス、データ型チェックなど)。しかし、Web アプリケーションでは、SQL インジェクション保護が最も重要です。

<!--- substitute the correct type for your db column --->
WHERE CAT_DESC = <cfqueryparam value="#ARGUMENTS.CAT_DESC#" 
                         cfsqltype="cf_sql_varchar">

改良点

CF8.0.1 以降でcfselectは、(配列だけでなく) クエリ オブジェクトにバインドできます。したがって、配列を作成する代わりに、関数から生のクエリを返すだけです。

    <cffunction name="getServiceType2" access="remote" returnType="query">
        <cfargument name="CAT_DESC" ....>

        <cfset var data="">

        <cfquery name="data" ..> 
           SELECT TheQueryColumnToDisplay, TheQueryColumnUsedForListValue
           FROM  ... 
           WHERE ... 
        </cfquery>

       <cfreturn data>
    </cffunction>

次に、displayおよびvalue属性に使用する列を指定します。

    <cfselect name="service" 
              bind="cfc:select.getServiceType2({catdesc})"
              display="TheQueryColumnToDisplay"
              value="TheQueryColumnUsedForListValue" ...>
于 2013-01-25T20:54:32.630 に答える
1

私の提案は、一度に 1 つのことを行うことです。あなたの特定の状況については、

まず、クエリを cfquery タグで使用できるようにします。

次に、関数に引数を渡す関数内で動作するようにします。

次に、関数を cfc 内に配置し、オブジェクトを作成して関数を呼び出すか、いずれかを使用して cfc ページから呼び出します。

最後にバインドを行います。

このアプローチにより、エラーがより見やすくなり、エラーに対して何かを行うことができます。

その他の観察

  1. クエリ パラメータを使用します。
  2. テキストの説明の代わりに id フィールドをクエリに渡してみてください
于 2013-01-25T18:23:31.347 に答える