(この回答が長すぎないことを願っています。既存の回答では十分な情報が得られなかったと思いますが、逆に行き過ぎていないことを願っています...)
CF には、変数を配置できるさまざまなスコープ (アプリケーション、セッション、URL、CGI など) があります。
これらの中には、明示的な宣言を使用する必要があるもの (たとえば、セッション変数は常にスコープを指定する必要があります) もあれば、変数を読み取るときに自動的にアクセスできるものもあります (たとえば、フォーム変数と URL 変数は、スコープ外の変数を使用して読み取ることができます) - 優先順位があります。ここでは、スコープ外の変数についてチェックするスコープを決定します。
この順序で一番下のスコープはvariables
スコープです。これは、現在のページ/オブジェクト インスタンス全体に適用されるスコープです。
新しい変数を設定するとき、スコープが設定されていない場合は、variables
スコープ内に作成されます。これはグローバルスコープであるため、同じ関数の異なるインスタンスと異なる関数の両方からアクセスできます。これにより、認識している問題が発生します。
変数がグローバル変数スコープに入らないようにするには、変数を関数のlocal
スコープに配置する必要があります。(技術的には、関数のarguments
スコープに配置できますが、これは人々を混乱させる可能性があります。)
以前のバージョンの CF では、ローカル スコープに明示的にアクセスする方法がありませんでしたvar
。ローカル スコープ内で変数を作成するには、キーワードを使用する必要がありました。一度作成すると、(読み取りと書き込みの両方で) 常に優先されます。変数のスコープ。
CF9 では、local
スコープは「適切な」スコープになり、明示的にアクセスできるようになったため、使用<cfset var x = 0 />
する代わりに書き込みが可能になりました。これの主な利点は、キーワードを使用できない<cfset local.x = 0 />
変数を作成する場合です。var
<cfquery name="local.qGetElementsByType" ...>
<cfloop index="local.lcv"...>
各変数を最初に作成するときにローカル スコープを適用するだけで、それが変数スコープに入らないようにすることができます。必要に応じて、var スコープを実行する場合と同様に、後続の読み取り/更新をスコープ解除できます。
(ただし、ブロック内など、スコープ外の変数にはスコープに関連する潜在的な問題が他にもあります。<cfloop query="queryname">
このため、何があっても常にすべての変数をスコープする必要があると主張する人もいます。)
要約すると、表示するコードを安全にするには、スコープを設定する必要があります。
qGetElementsByType
cfquery タグから
lvc
cfloop タグから
これらの変数は cfset で作成されないため、名前の前にlocal.
すでにvar
listCount 変数のスコープを設定しているため、同じ関数で再度行う必要はありません。オプションで<cfset local.listCount = local.listCount + 1>
(または実際に<cfset local.listCount++ >
は ) を使用できますが、これも好みの問題であり、変数スコープへのリークを防ぐために必要ではありません。 .
(補足: 理想的には、SQL インジェクションから保護するために cfqueryparam タグを使用する必要が#lcv#
あります。これはクエリのクエリであるにもかかわらず、これは依然として問題になる可能性があり、セキュリティ上安全にプレイすることを常にお勧めします。)
もちろん、それはこの関数だけです。他の関数も修正する必要があります。これを行う簡単な方法は、varscoperツールを使用してコードベース全体をスキャンし、スコープが必要な変数を特定することです。