ColdFusion-開発効率を求められる今だから知りたい高性能Webアプリケーションサーバー

第5回 ColdFusionでHTMLフォームのデータを扱う

この記事を読むのに必要な時間:およそ 4 分

第4回目の記事ではColdFusionでグラフを描画する例をご紹介しました。他の言語でグラフ描画をしようと思った場合,GDなどをインストールした上でラッパーライブラリーを介して操作するなど,グラフを描画するにも非常に煩雑な操作が伴います。対してColdFusionではcfchartタグcfchartseriesタグcfchartdataタグを用いて,HTMLのテーブルを構築するのと同じような感覚で,タグを記述するのみでグラフ描画を行うことができると分かりました。

今回はHTMLのフォームから送られてくるデータの処理の仕方を学びます。

"スコープ"という概念

今まで紹介していなかったColdFusion独自の概念として「スコープ」と言うものがあります。スコープとは,他の言語で言うところのローカルスコープ,グローバルスコープとは若干違った意味合いになります。

今までの例で何気なく使っていた変数は,全て『Variablesスコープ』というスコープの中に入っていました。例えば以下の例を実行してみましょう。以下の例ではクエリーを発行し,結果をqryという名前の変数に代入しています。また,strという名前の変数に「ColdFusion 8」という文字列を代入しています。その後,Variablesスコープをcfdumpしています。{cf_root}フォルダ({cf_root}はColdFusionをインストールしたディレクトリです。Windowsでは『C:\ColdFusion8』になります)内にある『wwwroot』の中に『gihyo』という名前のフォルダを作り,その中に『5』というフォルダを作ってください。『5』のフォルダの中に以下のような中身のファイルをvariables.cfmとして保存してください(ファイルのパスは{cf_root}/wwwroot/gihyo/5/variables.cfmになります)。なお保存時の文字コードはUTF-8としてください。その後,http://127.0.0.1:8500/gihyo/5/variables.cfmでアクセスしてみましょう。

<cfprocessingdirective pageEncoding="UTF-8" />
<cfcontent type="text/html; charset=UTF-8">
<cfquery datasource="cfartgallery" name="qry">
  SELECT
    COUNT(art.artID) AS num, art.mediaID
  FROM
    art
  GROUP BY
    mediaID
</cfquery>
<cfset str = "ColdFusion 8">
<cfdump var="#Variables#">

図1 variables.cfmの実行結果

図1 variables.cfmの実行結果

ご覧頂いて分かるとおり,Variablesスコープは構造体です(cfdumpしたとき青色になるものは構造体です。また「struct」というラベルが付いています)。そして構造体のキーとして「QRY」「STR」があり,その中にクエリーの結果や代入した文字列が保持されていることが分かります。つまり,今まで何気なく使用していたページ内で定義した変数は全てVariablesスコープという構造体の中に保存されていることがわかります。

また,cfdumpの結果を見て分かるとおり,ColdFusionは変数の大文字小文字を区別しません。従って,「Variables.qry」と書いても「Variables.QRY」と書いても同じ変数を参照します。しかしながら,変数の宣言時と参照時で違う綴りをしているとプログラミングミスに繋がる可能性があるため,CFMLテンプレート中では綴りは統一しておくことが望ましいでしょう。

HTMLフォームのデータを保持するFormスコープ

HTMLフォームからPOSTで送ったデータはFormスコープというVariablesスコープとは別のスコープに保存されます。以下の例を{cf_root}/wwwroot/gihyo/5/form.cfmとして保存してください。form.cfmにアクセス後,テキストフィールドに適当な文字を入力し「送信」というボタンをクリックしてみましょう。

<cfprocessingdirective pageEncoding="UTF-8" />
<cfcontent type="text/html; charset=UTF-8">
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<title>Formスコープ</title>
<cfif StructKeyExists(Form, 'submit')>
  <cfset str = "ColdFusion 8">
  <cfdump var="#Variables#" label="Variablesスコープの中身">
  <cfdump var="#Form#" label="Fromスコープの中身">
</cfif>
<form action="form.cfm" method="post">
  <p>何かテキストを入力してください:<input type="text" name="str" value=""><br>
  <input type="submit" name="submit" value="送信" ></p>
</form>

図2 form.cfm実行結果。「あいうえお」と入力して送信した。

図2 form.cfm実行結果。「あいうえお」と入力して送信した。

ご覧頂いて分かるとおり,POSTで送信されたデータがFormスコープに保持されていることが分かります。また,Variablesスコープとは別扱いになっていることも分かると思います(フォームと変数で同じ「str」という変数名を使っていますが,スコープが別になっているため上書きされていません)。ちょうどPHPでPOSTで送信された値が$POSTという連想配列に代入されるのと同じような感覚です。

なお,FormスコープもVariablesスコープと同様に構造体のため,変数の大文字小文字を区別しません。

さて,ここでいくつか見慣れないコードが出てきます。

StructKeyExists()関数は,第一引数に渡された構造体に,第二引数で渡されたキーが存在するかどうかを返す関数です。従って,StructKeyExists(Form, 'submit')とは,Formスコープに「submit」というキーが存在するかどうかを判定しています。つまり,cfifの部分で『HTMLフォームからデータが送信されたかどうか』を判定しています。

同じように変数が定義されているかどうかを調べる関数にはIsDefined()関数がありますが,こちらは少々厄介です。例えばIsDefined('Form.submit')とすると,Formスコープの中に「submit」という変数が定義されているかどうかを調べることもできますが,仮にそれが存在しなかった場合,Variablesスコープの「Form」という名前の構造体に「submit」と言うキーが存在するかどうかも調べてしまいます(つまりIsDefined('Variables.Form.submit')を実行しているのと等価です)。このようにIsDefined()関数は,参照可能な値をすべて辿っていって,定義されているかどうかを調べてしまうので,意図しない値を返すことがあります。また,参照可能な値をすべて辿るため,パフォーマンスの観点からもあまりお奨めできません。したがって,あるスコープに変数が定義されているかどうかを調べるのにはStructKeyExists()関数を使いましょう。

次に見慣れない関数としてSetEncoding()関数があります。これは,POSTで渡されてくるデータの文字コードを指定するものです。今回はUTF-8のページから自分自身にPOSTしているため,POSTの文字コードはUTF-8であると明示しています。例えば,文字コードがShift_JISのページからこのファイルにPOSTする場合は,<cfset SetEncoding("Form", "Shift_JIS")>と,Shift_JISのデータが送られてくると明示する必要があります。

著者プロフィール

酒井克幸(さかいかつゆき)

フリーのテクノロジーコンサルタント。サーバー選定やネットワーク設計などハードウェアレイヤーから,Webアプリケーションの実装(サーバーサイド,クライアントサイド共)などのソフトウェアレイヤーまでの幅広い経験を活かし,クライアント企業のWebアプリケーション構築支援を行っている。殊にAdobe製品(特にMacromedia)製品には精通している。

ブログcyano(シアノ)

コメント

コメントの記入