3

Coldfusionでデータベースクエリ/ストアドプロシージャを実行している場合、クエリから返されたフィールドを参照する適切な方法は何ですか?

<cfstoredproc procedure="proc_select_extern" datasource="stokkers">
    <cfprocparam type="in" value="#Session.Extern#" cfsqltype="cf_sql_varchar" maxlength="13">
    <cfprocresult name="extern">
</cfstoredproc>
<cfoutput query="extern">
   <cfset variables.some = extern.foo>
   OR 
   <cfset variables.some = foo>
</cfouput>

externには、foo、bar、foobarが含まれていると言います。書くことは許可されており、より良いですか:

 extern.foo;
 extern.bar;
 extern.foobar;

私はページを実行しているので、これらの「裸の」変数をたどるのが少し混乱することがよくあります。

 foo;
 bar;
 foobar;

スコープと適切なスコープに関する情報はたくさんありますが、クエリ出力については何も見つかりませんでした。

説明してくれてありがとう!

4

4 に答える 4

7

本当に重要な場所でスコーピングエラーが発生するのを防ぐため、常にスコープを設定することをお勧めします。

個人的には、クエリでcfoutputを使用し、スコープを設定する必要がないというアプローチが好きです。これは、他の言語の「WITH」と同等です。クエリは常にクエリ駆動型cfoutputタグ内のフォームスコープとURLスコープの前に評価されるため、そのインスタンスでスコープを省略しても問題は発生しません。CFCでは、「引数」とローカルスコープの両方がプリエンプティブになりますが、便利な表示用に設計された(適切に設計された)クエリ駆動型cfoutputには最適な場所ではないことに注意してください。

しかし、もう一度..他の人はあなたに違うことを言うでしょう(いくつかの情熱もあります:)。

于 2012-05-22T20:03:06.467 に答える
5

変数を完全にスコープしない場合、これにはスコープの問題があります。

余分な入力を正当化するのに十分な問題は発生しないと言われることがありますが、DRYではありませんが、ColdFusionにはスコープ評価順序があるため、コンテキストに関係なく機能するコードがある場合に必要です。

以下の「クエリループ」とは、cfloopまたは引数cfoutput付きを意味します。query

したがって、クエリループ内で使用できます。#columnname#

クエリループの内側または外側にでき ます。#queryName.columnName#

あなたはすべての場合にすべきです。 #cfScope.queryName.columnName#

これがうまくいかない例です。このようなコードを処理する必要がないことを願っていますが、ColdFusionの広範なスコープ評価の問題を指摘するのに役立ちます。

<cfset testcfc = new Test().scopeTest()>

<cfcomponent output="false">

    <cffunction name="scopeTest" access="public" output="true" returntype="void">
        <cfargument name="Query" type="query" required="false" default="#QueryNew("xarguments")#">
        <cfargument name="xlocal" type="string" required="false" default="This is not from a query; Arguments scope.">

        <cfset QueryAddRow(Arguments.Query, 1)>
        <cfset Arguments.Query["xarguments"][1] = "this is the arguments scope query">
        <cfset local.Query = QueryNew("xlocal")>
        <cfset QueryAddRow(local.Query, 1)>
        <cfset local.Query["xlocal"][1] = "this is the local scope query">
        <cfset Variables.Query = QueryNew("xVariables")>
        <cfset QueryAddRow(Variables.Query, 1)>
        <cfset Variables.Query["xVariables"][1] = "this is the variables scope query">

        <cfset local.xlocal = "This is not from a query; local scope.">

        <cfloop query="Query">
            <cfoutput>#xlocal#</cfoutput>
        </cfloop>

        <cfdump var="#Arguments#" label="Arguments">
        <cfdump var="#local#" label="local">
        <cfdump var="#variables#" label="Variables">
        <cfabort>
    </cffunction>

</cfcomponent>

出力の結果は次のとおりです。これはクエリからのものではありません。引数のスコープ。スコープ評価のドキュメントや他の人に信じてもらえることとは 反対です。

他の人が示唆しているように、出力行を変更して読み取ることができます<cfoutput>#Query.xlocal#</cfoutput>が、それも役に立ちません。代わりに、列が存在しないと言われます。に変更すると、またはの代わりにのバージョンを<cfoutput>#Query.xarguments#</cfoutput>使用していたことが示されます。ArgumentsQuerylocalVariables

では、どうでしょうか。

        <cfloop query="local.Query">
            <cfoutput>#xlocal#</cfoutput>
        </cfloop>

いいえ。それでも望ましい結果ではありません。では、クエリ名を出力に追加してみませんか。

        <cfloop query="local.Query">
            <cfoutput>#Query.xlocal#</cfoutput>
        </cfloop>

いいえ。それでも望ましい結果ではありません。正しい結果が得られることを確認したい場合は、すべてを完全にスコープする必要があります。

        <cfloop query="local.Query">
            <cfoutput>#local.Query.xlocal#</cfoutput>
        </cfloop>

これは誰もがやりたいよりもはるかに多くのタイピングですが、コードに厄介なバグが潜んでいないことを確認したい場合に必要です。

于 2012-05-23T10:25:20.857 に答える
3

私はあなたがすべてをスコープするべきだとあなたに言うだろうそれらの人の一人です。自分のコードや他のコードを読むときに本当に役立ちます。私は「間違いなく、それをスコープアウトしてください!」と言います。

以下は、私が通常クエリを実行して結果を出力する方法の例です。

<cfscript>
Q = MyCFC.getCustomers();
if (! isQuery(Q) || Q.RecordCount == 0) {
    writeOutput("No records found.");
}  else {
    for (i = 1; i lte Q.RecordCount; i++) {
        VARIABLES.Customer = "#Q.FirstName[i]# #Q.LastName[i]#";
        writeOutput(VARIABLES.Customer);
        writeOutput("<br>");
    }
}
</cfscript>
于 2012-05-22T20:10:01.567 に答える
2

これは、いつ必要なのか、いつスコープすることが価値があるのか​​についての素晴らしい議論です。

私は、CFCの内外を明確にするためだけに、常にスコーピングの方向に2つのペニーを投げます。必要な場合は、var q =''; 次に、qを参照するだけで、怠惰でDRYにスコープが含まれていると思われる場合にローカルスコープ変数を使用できます。

スコープが不十分なために作業したシステムとページの数がわからないため、何がどこから来たのかをデバッグする必要がありました。特に、グループバイと二次データが関係する複雑なレポートでは、非常に混乱する可能性があります。

あるピーブは、人々が(知っているかどうかにかかわらず)トリックを使用して、スコープなしでパラメータをデフォルト設定し、それが「変数」スコープに割り当てられ、コード内でフォームとURLを混合し、1つが上書きされることを期待しているところです。他の、および/またはスコープのない変数スコープの値。これにより、出力は常にデフォルトの変数バージョンの値を見つけることができます。もちろん、そのコードは期待どおりに動作しません...うーん!

クエリ属性を持つcfquery/cfoutput / cfloop内でも、わかりやすくするためにスコープを設定することをお勧めします。さらに、cfouput/cfloopをcfc/object内で使用できない理由はありません。

もちろん、非常に単純な出力の場合は、ページに他のスコープが混在していない非常に基本的な出力のCFCの外部で、「変数」スコープを削除することがありますが、これはまれです。

私にとっては、常に自分の価値観を正しく把握する習慣を身につけるほうが簡単です。

すなわち:

<cfprocresult name="Local.qExtern">

その後:

<cfoutput query='Local.qExtern'> 
    #Local.qExtern.szNameFirst# 
    #Local.qExtern.szNameLast# 
</cfoutput>

要約すると、最も単純な場合を除いて、常にスコーピングに傾く3つの理由を考えます。

明確さとメンテナンス

次のプログラマーにとって、そして6か月後の自分自身にとって、コードを少し見ることは、スコーピングしないことで節約できるいくつかのキーストロークよりもはるかに価値があります。これは、コードがループ中にクエリを単にダンプするよりも複雑で、他のロジックまたは変数/値が出力に散在する場合に特に当てはまります。

出血とロック

さらに、CFCでスコープが不適切な変数を使用している場合、特にデフォルトのスコープがローカルスコープではなく保護されたスコープに移動すると、変数が出血するリスクが確実に発生します。また、複数のメソッド*やシングルトンメソッドが共通の(保護された)スコープにアクセスし、その名前空間を使用しようとしている待機中のメソッド/リクエストからその変数をロックする必要がある場合にも、パフォーマンスが大幅に低下します(ああ、そうです、出血)。

速度:

最後に、JSや他の言語と同様に、スコープ付き変数は、デフォルトのスコープ内であっても、スコープなし変数よりもCFエンジンによってすばやく検出されると思います。

*脚注:これが発生するケースを明確にしたかったのです。スコープが不十分なシングルトン(たとえば、アプリケーションにキャッシュされたユーティリティクラス)は、システム/要求キューを遅くする可能性のある、意図しない保護されたスコープ変数のロックを引き起こす可能性が最も高いケースです。同じリクエスト内で同じ変数を使用する複数のメソッドは、変数のない変数がローカルスコープの変数(再帰関数、同じオブジェクト内の他のヘルパーメソッドを呼び出すメソッド)のように扱われ、通常はブリーディング(意図しない再利用)が発生する場合です。 /同じ変数を操作すると、予期しない結果が発生します)。

于 2013-03-05T04:09:33.687 に答える