掲載誌情報
タイトル リッチインターネットアプリケーションを開発しよう! 第3回
サブタイトル ColdFusion MXとFlash MXで作るリッチインターネットアプリケーションをMVCモデルで学ぶ
【要約】
 連載第3回では、第2回で構築したサーバー環境に対してプログラミングを行っていくこととする。今回は、主にColdFusion MXでバックオフィス側の処理に関するプログラミングを中心に開発を行っていく。

【概要】
 今回はFlash MXで作成されたリッチなインターフェースをフロントエンドでは使用せず、ブラウザーベースの一般的なWEBアプリケーションの開発を行う事で、ColdFusion MXがどのようにデータベースとアクセスするか、そしてどのように各機能をコンポーネント化するかを学んでいくことにする。プログラミングのオーサリング環境も前回クライアントマシンにインストールしたMacromedia Dreamweaver MXを使って、RDS(リモート開発サービス)にてリモートでサーバーへ接続してColdFusionコンポーネントの作成を行う。
 先ず初めに、ColdFusionMXを使っての簡単なプログラミングを学び、次に「勤怠管理システム」の一機能である「新規ユーザ登録」の実装を通して、実際のデータベースに対してデータの登録を行う。そして「勤怠管理システム」で必要な各機能のコンポーネント化を行いながら、ColdFusion MXのプログラミングの解説を行っていくこととする。

1. ColdFusion MXでのプログラミング
  前回でも少し触れたが、ColdFusion MX では、CFML(ColdFusion Markup Language)を用いて開発を行う。CGIのような難しいスクリプト言語を記述しなくても、HTML言語に類似したタグ記述によって、各種演算処理に加え、データベースとの連携が行え、比較的簡単にアプリケーションを構築することができる。
CFMLには、CFMLタグとCFML関数が用意されており、これらを使用してプログラミングを行う。
代表的なCFMLタグ、CFML関数には次のようなものがある。
     
 
CFMLタグ 概要
cfset 変数を定義、値を代入する。
cfif, cfelse, cfelsif 条件分岐を行う。
cfquery データベースに対してデータ取得、登録、更新、削除などの操作を行う。
cfqueryタグ間にSQL文を記述することで、データベースに対するデータ操作を行う。
ColdFusionではデータベースに対する問合せをクエリと呼ぶ。
cfoutput 変数や、クエリの結果を出力する。
cfloop 一連の処理や表示出力を繰り返す。
     
 
CFML関数 概要
Right, Left 文字列の先頭または末尾から指定された文字数分だけ文字列を抽出する。
Find 指定された文字列から特定の文字列を探す。
IsNumeric 指定された変数の値が数値であるかを判定する。
 
※上記以外にも、高度なタグや文字列関数、配列関数、算術関数など、各種タグ・関数が用意されている。

CFMLの詳細については、ColdFusion MXに付属のオンラインドキュメント「CFMLリファレンス」を参考にしていただきたい。
さて、先程紹介したCFMLで記述したプログラムファイルはどのように動作するのだろうか。
通常、HTMLベースのWebサイトでは、基本的にHTMLファイルに記述された内容をそのまま、Webサーバーからブラウザに返すことでWebページが表示される仕組みになっている。
一方、CFMLベースのWebサイトでは、特定の拡張子(.cfm)をもつページにリクエストがあると、ColdFusion ServerによってCFMLが実行された後、実行結果がブラウザに返され、Webページが表示される仕組みとなる。
  1-1. 開発用クライアント環境の準備
    それでは、実際にColdFusion MXのプログラミングを行っていくが、リモートサーバー上に配置するファイルを開発用クライアント環境からプログラミングするために、まずは、Dreamweaver MXの設定を行う。
リモートファイルの管理には、ColdFusion MX / Dreamweaver MXで提供されているRDS(リモート開発サービス)を利用する。

Dreamweaver MXを起動した後、次の操作を行う。
(1) メニューバーから[サイト]-[新規サイト]を選択する。
(2) ダイアログボックスの最上部にある [基本] タブをクリックする。
以降、ウィザード形式で、必要事項を入力しながらサイト定義設定を行っていく。
(3) サイト名を入力する。
ここでは、「日経Linux」とした。
スクリーン
(4) サーバーテクノロジーを選択する。
ColdFusionのプログラミングを行うので、「はい」をクリックし、「ColdFusion」を選択する。
スクリーン
(5) 開発ファイルの操作方法を選択する。
RDSを利用して、リモートサーバーに接続するため、「FTPまたはRDSを使用してテストサーバー上で直接ファイルを編集」を選択する。
また、サーバー上のプログラムファイルを編集する際、一旦ローカルマシンにファイルがダウンロードされるため、ファイルが格納されるローカルマシン上の作業ディレクトリを入力する。
スクリーン
(6) テストサーバーへの接続方法を設定する。
「RDS」を選択後、「設定」ボタンをクリックする。
次に、設定ボタンをクリックして表示された「RDSサーバーの設定」ダイアログボックスで、接続するリモートサーバーの情報を入力する。
前回(第2回)、ColdFusion MXのインストールを行ったが、ここではそのインストール内容に基づいた情報を入力する。
「フルホストディレクトリ」には、Webサーバーの、プログラムファイルを配置するディレクトリを絶対パスで入力する。本連載では、Webサーバーのドキュメントリートディレクトリを設定したとして話を進めさせていただく。
尚、「パスワード」にはColdFusion MXのインルトール時に設定したRDSのパスワードを入力する。
スクリーン
(7) リモートサーバーのルートURLを設定する。
(6)で設定したフルホストディレクトリに対応するURLを入力する。
スクリーン
(8) チェックイン/チェックアウト機能を設定する。
Dreamweaver MXには複数ユーザで共同作業をする場合に便利な機能としてチェックイン/チェックアウト機能 ※注 が用意されているが、ここでは、1人での作業と想定し、「チェックイン/チェックアウト機能を有効にしない」を選択する。
複数ユーザで共同開発を行う場合は、チェックイン/チェックアウト機能を利用した方が良いだろう。
スクリーン
※注: リモートサーバー上のプログラムファイルを複数のユーザで作成/管理する場合、注意していないと、同じファイルを同時に上書き更新してしまう可能性がある。チェックイン/チェックアウト機能を利用すると、ファイル作業時にDreamweaver MXによってチェックアウト(持ち出し)とチェックイン(返却)が自動管理される。そのため、チェックアウト中のファイルは別ユーザによる編集が不可となり、ファイル管理が容易になる。
(9) 設定内容を確認し、「終了」ボタンをクリックする。
スクリーン
(10) リモートサーバーへの接続を確認する。
サイトパネルにて、先程設定したサイト名および、「リモートビュー」をプルダウンで選択すると、リモートサーバーのディレクトリ/ファイルが表示される。
リモートサーバー上の情報が正しく表示されていれば、設定は完了だ。
スクリーン

次に、これから新規作成していくプログラムファイルの文字コードを設定しておく。
今回の連載では、文字コードに「UTF-8」を使用しているので、Dreamweaver MXで次の設定を行う。
(1) メニューバーから「編集」-「環境設定」を選択する。
(2) カテゴリから「新規ドキュメント」を選択する。
(3) 「エンコーディング初期設定」で「UTF-8(Unicode)」を選択する。
(4) 「OK」ボタンをクリックする。
  1-2. サンプルプログラムの作成
    準備が整ったところで、早速ColdFusion MXのプログラミングを行ってみる。
まずは、CFMLがどのようなものなのか、簡単なプログラムを作成してみよう。

(1) 初めにリモートサーバー上にファイルを作成する。
作成手順は次のようになる。
A) Dreamweaver MXで先程設定を行ったサイトへ接続する。
その際、サイトパネルのプルダウンで「リモートビュー」を選択しておく。
B) サイトパネル内のルートディレクトリを右クリックし、表示されたメニューから「新規フォルダ」を選択する。
リモートサーバー上にディレクトリが作成されるので、任意の名前をつける。
ここではディレクトリ名を「step1」とした。
スクリーン
C) 同様に「step1」ディレクトリを右クリックし、今度は「新規ファイル」を選択する。
ファイルが作成されるので、ファイル名を「sample1.cfm」とする。
D) 作成したファイル名をダブルクリックし、ファイルを開く。
E) メニューバーより「表示」-「コード」を選択する。
スクリーン
(2) 次にsample1.cfmに以下のソースコードを記述し、ファイルを保存する。
<cfprocessingdirective pageencoding="UTF-8">
<cfset price = 145> <!--- 単価 --->
<cfset amount = 5> <!--- 個数 --->
<cfset total = price * amount> <!--- 合計金額を計算 --->
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <title>日経Linuxサンプル</title>
</head>
<body>
 <!--- 合計金額の表示 --->
 <cfoutput>
 お買い上げありがとうございます。合計金額は#total#円です。
 </cfoutput>
</body>
</html>
(3) ファイルを保存したら、プログラムを実行してみよう。
ブラウザを起動して「http://<ホスト名またはIPアドレス>/step1/sample1.cfm」にアクセスすると以下のような画面が表示されるはずだ。
スクリーン
以上のプログラムは、単価と個数を計算し、計算結果をブラウザに表示するという非常にシンプルなものだ。
まず、ソースコード中、以下の部分で、単価、個数の値を格納する変数price, amountへ値を代入し、次に、単価、個数から合計金額を計算し、結果を変数totalへ代入している。
変数への値代入を行うには「cfset」CFMLタグを用いる。
<cfset price = 145> <!--- 単価 --->
<cfset amount = 5> <!--- 個数 --->
<cfset total = price * amount> <!--- 合計金額を計算 --->
最後に、以下の部分で、計算結果をブラウザに表示している。
ブラウザに変数の値を表示するには、「cfoutput」タグを用いる。
表示する変数の前後に「<cfoutput>」と「</cfoutput>」を記述することで、ブラウザには変数の値が表示される。ColdFusionでは、変数を表す場合、変数名を「#」で囲み「#接頭辞.フィールド名#」(接頭辞は省略可能)とする。「#」で囲んでおかないと、変数名自体がブラウザに表示されることになる。
<!--- 合計金額の表示 --->
<cfoutput>
お買い上げありがとうございます。合計金額は#total#円です。
</cfoutput>
ちなみに、以下の部分では、<cfprocessingdirective>タグを用いて、ページエンコーディングを指定している。
ColdFusion MXでは、作成したプログラムファイルの文字コードを<cfprocessingdirective>タグで指定しておく。
今回の連載では「UTF-8」を使用しているので、「pageencoding="UTF-8"」としている。
<cfprocessingdirective pageencoding="UTF-8">
  1-3. ColdFusionコンポーネントの作成
    このように、ColdFusion MXでは、通常HTMLタグ中にCFMLタグを記述してプログラムを作成する形となり、直感的に分かりやすく、容易なWebアプリケーション開発が可能となる。
ただ、一方で、ユーザインターフェース(HTML)とビジネスロジック(業務処理の流れやデータベースアクセスロジック)が混在する形になるため、アプリケーションの規模が大きくなると、再利用性の高いビジネスロジックの開発が容易ではなくなる。類似した処理を複数のページで何度も書くのはやはり面倒だ。
そのような問題を解決するための最適な方法として、ColdFusion MXでは、ColdFusionコンポーネントという技術が提供されている。
ColdFusionコンポーネントとして作成することで、再利用可能なビジネスロジックや特定のアプリケーションに依存しないビジネスロジックの開発が可能となる。
また、ColdFusionコンポーネントはColdFusion MXで作成されたWebページからのみでなく、Flashで作成したアプリケーションからも利用することができ、本連載の最終目的であるリッチインターネットアプリケーションの開発には欠かせない。
そこで、早速、先程作成した「sample1.cfm」をコンポーネント化してみる。

(1) 先程と同じ手順で、リモートサーバー上の「step1」ディレクトリ下に、ファイル「calc.cfc」を作成する。次に同ファイルに以下のソースコードを記述し、保存する。
<cfcomponent>
 <cfprocessingdirective pageencoding="UTF-8">
 <cffunction name="totalCalc" access="remote" returnType="numeric" output="false">
  <cfargument name="price" type="numeric" required="true">
  <cfargument name="amount" type="numeric" required="true">
  <cfset total = arguments.price * arguments.amount>
  <cfreturn total>
 </cffunction>
</cfcomponent>
ColdFusionコンポーネントは、ある特定の処理をカプセル化した関数(メソッド)の集まりだ。
関数であるため、当然、必要な情報を受け取り(引数)、処理の結果を返す(戻値)ことができる。
1つのコンポーネント内には、類似した目的を持つ関数(メソッド)を複数提供することが可能だ。
開発言語であるJavaやC++のクラスと同じようなイメージだと思ってもらえれば、分かりやすいだろう。
ここでは、1-2.で作成した「sample1.cfm」の、合計値を計算していた部分(ビジネスロジック)をコンポーネント化し、次のようなメソッドをもつコンポーネント「calc」を作成した。
メソッド名 totalCalc
処理概要 単価と個数から合計金額を算出し、算出結果を返す
引数 単価 個数
戻値 合計金額
尚、コンポーネントの作成といっても、実は1-2.で作成した「sample1.cfm」と同じくCFMLで記述するという点は何も変わらない。異なる点としては、ファイルの拡張子が「.cfc」になっているということと、コンポーネントを定義するためのタグを使用しているという点だ。
ファイル名から拡張子「.cfc」を除いた部分がコンポーネント名となる。
以下にColdFusionコンポーネント作成に用いるタグを紹介する。
CFMLタグ 内 容
cfcomponent コンポーネントであることを定義する。
コンポーネント内部の記述の開始と終了を明示するためのタグ。
cffunction コンポーネントがもつメソッドを宣言する。
cffunctionタグ内に、メソッドが呼ばれた際の処理を記述する。
代表的なタグの属性には次のものがある。
name属性
  メソッド名を指定する。
returnType属性
  メソッドが返す戻値のデータ型を指定する。
指定する値としては、例えば次のようなものがある。
numeric(数値型)、string(文字列型)、query(クエリ)、void(値を返さない)
cfargument メソッドが呼ばれる際の引数を宣言する。
代表的なタグの属性には次のものがある。
name属性
  引数名を指定する。
type属性
  引数のデータ型を指定する。
指定する値としては、例えば次のようなものがある。
numeric(数値型)、string(文字列型)
cfreturn メソッドが実行された結果を戻り値で返す。
返す値を<cfreturn 値>のように記述する。
「cffunction」タグ内で、「cfargument」タグで宣言した引数を参照するには、「arguments.引数名」と記述する。
(2) 同様に「step1」ディレクトリ下に、ファイル「sample2.cfm」を作成、以下のソースコードを記述し、保存する。
<cfprocessingdirective pageencoding="UTF-8">

<!--- コンポーネントの呼出 --->
<cfinvoke component="calc" method="totalCalc" returnvariable="total">
 <cfinvokeargument name="price" value="145">
 <cfinvokeargument name="amount" value="5">
</cfinvoke>
(A)

<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <title>日経Linuxサンプル</title>
</head>
<body>
 <!--- 合計金額の表示 --->
 <cfoutput>
 お買い上げありがとうございます。合計金額は#total#円です。
 </cfoutput>
</body>
</html>
1-2.で作成した「sample1.cfm」との違いは(A)の部分のみである。
(A)では、先程作成したCFC「calc」を呼び出し、結果を変数「total」で受け取っている。
以下にColdFusionコンポーネント呼び出しに用いるタグを紹介する。
CFMLタグ 内 容
cfinvoke コンポーネントを呼び出す。
代表的なタグの属性には次のものがある。
component属性
  呼び出すコンポーネント名を指定する。
method属性
  呼び出すメソッド名を指定する。
returnvariable属性
  メソッドの戻値が格納される変数名を指定する。
cfinvokeargument メソッドへの引数を指定する。
cfinvokeタグの内側に記述する。
代表的なタグの属性には次のものがある。
name属性
  メソッドで指定されている引数名を指定する。
value属性
  引数として渡す値を指定する。
(3) ファイルを保存したら、プログラムを実行してみよう。
ブラウザを起動して「http://<ホスト名またはIPアドレス>/step1/sample2.cfm」にアクセスすると1-2.の実行結果と同じ画面が表示されるはずである。
2. 勤怠管理システムのColdFusionコンポーネント作成
  さて、いよいよ、本連載での構築目標である勤怠管理システムについて、データベースとの連携を行うビジネスロジックをプログラミングしていく。
     
  2.1 ユーザ新規登録処理
    今回構築する勤怠管理システムで実装する各機能は、データベースに対して、登録(Insert)・参照(Select)・更新(update)・削除(delete)のいずれかのSQL文(クエリ)を発行することになるが、先ずは比較的簡単な処理である「ユーザ新規登録」の作成を通して、ColdFusion MXではどのようにデータを受け取り、どうやってデータベースに登録するかを解説する。

(1) 入力されたユーザ情報をデータベースへ登録するColdFusionコンポーネントを作成する
前回(第2回)で要件定義・仕様設計を行ったとおり、「新規ユーザ入力」機能は、ユーザ情報として、「UserID」、「Password」、「Name」、「E-Mail」をデータベースに登録する機能だ。
よって、ここでは、次のようなメソッドをもつコンポーネント「user」を作成する。
メソッドの機能としては、ユーザ情報として「UserID」、「Password」、「Name」、「E-Mail」を受け取り、それらの情報をデータベースへ格納するというものだ。
メソッド名 userRegist
処理概要 UserTableに指定情報を登録する。
引数 UserID Password Name Email
戻値 なし
リモートサーバー上に「step2」ディレクトリを作成、「step2」ディレクトリ下にファイル「user.cfc」を作成する。
更に以下のソースコードを記述し、保存する。
<cfcomponent>
 <cfprocessingdirective pageencoding="UTF-8">
 <cffunction access="remote" name="userRegist" output="false" returntype="void">
  <cfargument name="userID" type="string" required="true">
  <cfargument name="password" type="string" required="true">
  <cfargument name="name" type="string" required="true">
  <cfargument name="email" type="string" required="true">

  <cfquery name="insertUserQry" datasource="NikkeiLinux">
   INSERT INTO UserTable
   (
    UserID,
    Password,
    Name,
    Email
   )VALUES(
    '#arguments.userID#',
    '#arguments.password#',
    '#arguments.name#',
    '#arguments.email#'
   )
  </cfquery>
(A)

  <cfreturn>
 </cffunction>
</cfcomponent>
(A)の処理がデータベースの操作を行っている部分である。
ColdFusionでデータベースを操作するには「cfquery」タグを用いる。

「cfquery」タグを使用したデータベース操作でポイントになるのは次の点だ。
「datasource」属性へのDSN指定
  datasource属性には、前回(第2回)「ColdFusion MXでのDSN設定を行う」で設定したDSN(Data Source Name)※注1を指定する。この設定により、指定したデータベースへのアクセスが可能になる。
「cfquery」タグ内にSQL文を記述
  <cfquery>〜</cfquery>タグ間に、データベースに発行するSQL文を記述する。

※注1 データベースにMySQLを利用する場合、DSNの設定で、接続文字列を指定しておく必要がある。
設定方法は下記のようになる。
  1. ColdFusion MXの管理画面にログインする
  2. 管理画面トップ左側のナビゲーションから「データソース」を選択する。
  3. 使用するデータソース名をクリックする。
  4. [詳細設定の表示]ボタンを押して、詳細設定画面を開いた後「接続文字列」の部分に「useUnicode=true&characterEncoding=euc-jp」と記述する。
上記、「euc-jp」の部分はMySQLで使用している文字コードとなる。読者の環境に合わせて適宜読み換えていただきたい。
  5. 送信ボタンをクリックする。

さて、SQL文であるが、今回の場合、テーブル「UserTable」の各フィールドにレコードを挿入するため、次のようになる。
INSERT INTO UserTable (UserID, Password, Name, Email)
VALUES ('設定値', '設定値', '設定値', '設定値')
ソースコードでは、上記 「ユ設定値ユ」 の部分が「'#arguments.userID#'」のようになっているが、これはメソッドの引数である「arguments.userID」変数だ。
このように、SQL文中に「#」で囲んだ変数名を記述することで、動的なSQL文の実行が可能となる。
(2) 新規ユーザ入力ページの作成
次に、(1)で作成した「user.cfc」の動作を確認するため、Web上の「新規ユーザ入力」ページから入力を行い、入力情報をデータベースに格納する簡易アプリケーションを作成してみる。
「step2」ディレクトリ下に、ユーザ情報を入力するページ「registForm.cfm」、および、入力された情報をデータベースへ登録し、完了メッセージを表示するページ「registUser.cfm」を作成する。
ソースコードはそれぞれ次のようになる。

「registForm.cfm」
<cfprocessingdirective pageencoding="UTF-8">
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <title>日経Linuxサンプル</title>
</head>
<body>
 <center>
 <form name="myForm" method="post" action="registUser.cfm">
 <table border="0" cellpadding="0" cellspacing="0" width="300">
  <tr>
   <td width="100">UserID</td>
   <td width="200"><input name="fmUserID" type="text" size="20"></td>
  </tr>
  <tr>
   <td>Password</td>
   <td><input name="fmPassword" type="text" size="20"></td>
  </tr>
  <tr>
   <td>Name</td>
   <td><input name="fmName" type="text" size="20"></td>
  </tr>
  <tr>
   <td>E-Mail</td>
   <td><input name="fmEmail" type="text" size="20"></td>
  </tr>
 </table>
 <br>
 <input type="submit" value="登録">
 </form>
 </center>
</body>
</html>
これは、HTMLのformを配置し、登録ボタンがクリック(submit)されたら、「registUser.cfm」にリンクするページとなる。

「registUser.cfm」
<cfprocessingdirective pageencoding="UTF-8">

<cfset setEncoding("Form","UTF-8")> (A)

<cfinvoke component="user" method="userRegist">
 <cfinvokeargument name="userID" value="#Form.fmUserID#">
 <cfinvokeargument name="password" value="#Form.fmPassword#">
 <cfinvokeargument name="name" value="#Form.fmName#">
 <cfinvokeargument name="email" value="#Form.fmEmail#">
</cfinvoke>
(B)

<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <title>日経Linuxサンプル</title>
</head>
<body>
 <center>
 ユーザの登録が完了しました。
 </center>
</body>
</html>
これは、「registForm.cfm」から渡されたform変数の情報をデータベースへ登録し、結果を表示するページとなる。
実処理としては、(B)の部分で、先程作成したColdFusionコンポーネントを呼び出しているだけである。
なお、(A)の部分では、「registForm.cfm」から受け取ったform変数をColdFusion内で正常に処理できる様、form変数の文字コードをエンコードしている。
(3) 作成したページにアクセスしてみる
ブラウザを起動して「http://<ホスト名またはIPアドレス>/step2/registForm.cfm」にアクセスする。
ユーザ情報を入力したら、「登録」ボタンをクリックする。
スクリーン
正常に登録できたら、次の画面が表示される。
スクリーン
MySQLでUserTableを確認してみると、実際にレコードが追加されているはずだ。
これで、ユーザ情報の登録が行えるようになったが、この登録ページを他の人が利用すると考えた場合、利用するユーザがいつも正しくデータを入力するとは限らない。
やはり、最低限の入力チェックは必要となるだろう。そこで、次に入力チェック機能を組み込んでみる。
(4) 入力チェック機能を組み込む
ここでは、先程作成したColdFusionコンポーネントに以下の入力チェックを追加する。
・入力項目に1つでも未入力の項目がある場合はエラーとする。
・UserID、Passwordは半角英数字で入力された場合のみ登録を受け付ける。
・入力されたUserIDが既にデータベースに登録済みの場合はエラーとする。

「user.cfc」を次の様に修正する。
<cfcomponent>
 <cfprocessingdirective pageencoding="UTF-8">

 <cffunction name="userRegist" access="remote" returnType="string" output="false"> (A)

  <cfargument name="userID" type="string" required="true">
  <cfargument name="password" type="string" required="true">
  <cfargument name="name" type="string" required="true">
  <cfargument name="email" type="string" required="true">

  <!--- 未入力チェック --->
  <cfif arguments.userID EQ "" OR arguments.password EQ "" OR arguments.name EQ "" OR arguments.email EQ "">
   <cfreturn "未入力の項目があります。全ての項目を入力してください。"> (A)
  </cfif>
(B)

  <!--- 半角英数字チェック --->
  <cfif REFindNoCase("^[A-Za-z0-9]+$",arguments.userID) IS 0 OR REFindNoCase("^[A-Za-z0-9]+$",arguments.password) IS 0>
   <cfreturn "UserID、Passwordは半角英数字で入力してください。"> (A)
  </cfif>
(C)

  <!--- UserID重複チェック --->
  <cfquery name="checkUserQry" datasource="NikkeiLinux">
   SELECT UserID FROM UserTable WHERE UserID = '#arguments.userID#'
  </cfquery>
  <cfif checkUserQry.RecordCount GT 0>
   <cfreturn "UserIDが重複しています。別のUserIDを入力してください。"> (A)
  </cfif>
(D)

  <!--- User情報登録 --->
  <cfquery name="insertUserQry" datasource="NikkeiLinux">
   INSERT INTO UserTable
   (
    UserID,
    Password,
    Name,
    Email
   )VALUES(
    '#arguments.userID#',
    '#arguments.password#',
    '#arguments.name#',
    '#arguments.email#'
   )
  </cfquery>

  <cfreturn ""> (A)
 </cffunction>
</cfcomponent>
ここでのポイントは次のとおりである。
(A) ColdFusionコンポーネントの実行結果を、呼出元へ返す。
入力チェックの結果、エラーである場合は実行結果としてエラーメッセージを返すようにする。(正常にデータベースへの登録を行った場合は、空文字を返す)
また、戻値として文字列を返すようにするため、「cffunction」タグの「returnType」属性を「string」としている。
(B) 未入力チェックを行う。
各引数の値をチェックし、空文字(「モモ」)でないかをチェックする。
条件判定には「cfif」タグを用いる。結合演算子「OR(または)」は、複数の条件式を組み合わせる際に使用する。
(C) 半角英数字チェックを行う。
引数UserID、Passwordの値をチェックし、半角英数字であるかをチェックする。
半角英数字であるかどうかは、「REFindNoCase」関数を用いて判別することができる。
「REFindNoCase」関数の使用方法は、ColdFusion MXのリファレンスマニュアルを参考にしていただきたい。
(D) UserIDの重複チェックを行う。
入力されたUserIDがデータベースに登録済みであるかどうかは、次のSQL文を実行し、返されたレコードの件数を調べることで判別可能だ。
レコード件数が、0件であれば指定したUserIDはまだ登録されていないことになる。
SELECT UserID FROM UserTable WHERE UserID = 'チェックするUserID'
したがって、CFMLでの記述は次のようになる。
<cfquery name="checkUserQry" datasource="NikkeiLinux">
 SELECT UserID FROM UserTable WHERE UserID = '#arguments.userID#'
</cfquery>
<cfif checkUserQry.RecordCount GT 0>
 <cfreturn "UserIDが重複しています。別のUserIDを入力してください。">
</cfif>
SQL文を実行し、データベースから返されたレコード情報は「cfquery」タグの「name」属性で指定した変数に全て格納される。この変数はクエリ変数と呼ばれ、今まで登場した変数とは異なり、単一の値ではなく、複数の情報を持っている。
レコード件数は、「クエリ変数名. RecordCount」と記述することで参照可能だ。
上記ソースコードでは、レコード件数が0件より大きいかを判定している。

「registUser.cfm」を次の様に修正する。
<cfprocessingdirective pageencoding="UTF-8">
<cfset setEncoding("Form","UTF-8")>

<cfinvoke component="user" method="userRegist" returnvariable="ret"> (A)
 <cfinvokeargument name="userID" value="#Form.fmUserID#">
 <cfinvokeargument name="password" value="#Form.fmPassword#">
 <cfinvokeargument name="name" value="#Form.fmName#">
 <cfinvokeargument name="email" value="#Form.fmEmail#">
</cfinvoke>

<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <title>日経Linuxサンプル</title>
</head>
<body>
 <center>

 <cfif ret EQ "">
  ユーザの登録が完了しました。
 <cfelse>
  <cfoutput>#ret#</cfoutput>
 </cfif>
(B)

 </center>
</body>
</html>
ここでのポイントは次のとおりである。
(A) ColdFusionコンポーネントからの実行結果を受け取る。
実行結果は「cfinvoke」タグの「returnvariable」属性に指定した変数に格納される。
(B) 実行結果に応じて、ブラウザに表示するメッセージを切り替える。
ここでは、実行結果が正常である場合は、完了メッセージを、異常である場合は、エラーメッセージ(ColdFusionコンポーネントから返されたメッセージ)を表示している。

これで入力チェックの追加は完了だ。
  2.2 ユーザ一覧参照機能
    次に、今度は先程登録したユーザ情報をデータベースから取り出し、ユーザ一覧を表示する簡易アプリケーションを作成してみる。

(1) ユーザ情報をデータベースから取得するColdFusionコンポーネントを作成する。
ここでは、次の機能をもつメソッドを作成する。
メソッド名 userListGet
処理概要 UserTableからユーザ一覧情報を取得し、取得データを返す。
引数 なし
戻値 クエリ
尚、ユーザ情報を取得するメソッドおよび、2.1で作成したユーザ情報を登録するメソッドは、共にユーザ情報を管理するという共通の目的をもったメソッドだ。よって、両メソッドはユーザ情報管理コンポーネントとして、1つのコンポーネントにまとめた方が分かりやすい。
したがって、ここで作成するメソッドは、「user.cfc」に追加することにする。

「user.cfc」を次のように追加修正する。
<cfcomponent>
 <cfprocessingdirective pageencoding="UTF-8">
 <cffunction name="userRegist" access="remote" returnType="string" output="false">
  <cfargument name="userID" type="string" required="true">
  <cfargument name="password" type="string" required="true">
  <cfargument name="name" type="string" required="true">
  <cfargument name="email" type="string" required="true">
    ・・・省略・・・
  <cfreturn "">
 </cffunction>

 <cffunction name="userListGet" access="remote" returnType="query" output="false">

  <cfquery name="selectUserQry" datasource="NikkeiLinux">
   SELECT UserID, Password, Name, Email
   FROM UserTable
  </cfquery>
(A)

  <cfreturn selectUserQry>
 </cffunction>
(B)
追加する
メソッド

</cfcomponent>
ここでのポイントは次のとおりである。
(A) データベースからユーザ情報を取得する。
UserTableから全てのユーザ情報を取得するには、次のSQL文を実行する。
したがって、<cfquery>タグを用いて、下記SQL文を指定している。
SELECT UserID, Password, Name, Email FROM UserTable
SQL文を実行し、データベースから返されたレコード情報は「cfquery」タグの「name」属性で指定した「selectUserQry」クエリ変数に、全て格納される。
(B) データベースから取得した情報を、呼出元へ返す。
「cfreturn」タグで変数「selectUserQry」を指定することで、レコード情報が全て呼び出し元に返される。
また、戻値としてクエリ変数を返すようにするため、「cffunction」タグの「returnType」属性を「query」としている。
クエリ変数を用いたレコード情報への参照方法は次のプログラムで説明する。
(2) ユーザ情報一覧ページの作成
次に、(1)で作成した「user.cfc」の動作を確認するため、ユーザ情報一覧ページを作成する。
「step2」ディレクトリ下に、「listUser.cfm」を作成する。
ソースコードは次のようになる。
<cfprocessingdirective pageencoding="UTF-8">

<cfinvoke component="user" method="userListGet" returnvariable="ret"> (A)

<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <title>日経Linuxサンプル</title>
</head>
<body>
 <center>
 <table border="1" cellpadding="0" cellspacing="0" width="600">
  <tr>
   <td width="150" align="center">UserID</td>
   <td width="150" align="center">Password</td>
   <td width="150" align="center">Name</td>
   <td width="150" align="center">E-mail</td>
  </tr>

  <cfoutput query="ret">
  <tr>
   <td>#ret.UserID#</td>
   <td>#ret.Password#</td>
   <td>#ret.Name#</td>
   <td>#ret.Email#</td>
  </tr>
  </cfoutput>
(B)

  </tr>
 </table>
 </center>
</body>
</html>
ここでのポイントは次のとおりである。
(A) ColdFusionコンポーネントからの実行結果を受け取る。
実行結果は「cfinvoke」タグの「returnvariable」属性で指定した変数に格納される。
よって、データベースから取得したレコード情報がクエリ変数「ret」に格納されることになる。
(B) 返されたユーザ情報を表示する。
レコード情報を全て出力するには、「cfoutput」タグを用い、「query」属性にクエリ変数を指定する。
すると、データベースから返されたレコード毎に「cfoutput」で囲まれた全てのコードが繰り返し出力される。
データベースから返された任意のフィールドを指定するためには、「クエリ変数名.フィールド名」と記述する。
  2.3 タイムカード出社打刻機能
    続いて、出社時のタイムカード出社打刻に必要なColdFusionコンポーネントの実装を行う。
タイムカード出社打刻機能は、ユーザが入力した「UserID」、「Password」を基にユーザを特定し、出社記録を行う機能だ。
出社打刻の流れは前回(第2回)にも登場した下記アクティビティ図のとおりとなる。
 (図:uml/アクティビティ図.pdf)
したがって、次のようなメソッドをもつコンポーネントを作成する。
メソッド名 commingStamp
処理概要 チェック結果が正常な場合、TimecardTableに出社打刻情報を登録する。
引数 UserID Password
戻値 エラーメッセージ
「step2」ディレクトリ下にファイル「timecard.cfc」を作成し、次のソースコードを記述する。
<cfcomponent>
 <cfprocessingdirective pageencoding="UTF-8">
 <cffunction name="commingStamp" access="remote" returnType="string" output="false">
  <cfargument name="userID" type="string" required="true">
  <cfargument name="password" type="string" required="true">

  <!--- 入力チェック --->
  <cfif arguments.userID EQ "" OR arguments.password EQ "">
   <cfreturn "UserID、Passwordを入力してください。">
  </cfif>
(A)

  <!--- UserID、Password妥当性チェック --->
  <cfquery name="checkUserQry" datasource="NikkeiLinux">
   SELECT * FROM UserTable
   WHERE UserID = '#arguments.userID#'
   AND Password = '#arguments.password#'
  </cfquery>
  <cfif checkUserQry.RecordCount EQ 0>
   <cfreturn "UserID、またはPasswordが誤っています。">
  </cfif>
(B)

  <!--- 出社済みチェック --->
  <cfquery name="checkTimecardQry" datasource="NikkeiLinux">
   SELECT * FROM TimecardTable
   WHERE UserID = '#arguments.userID#'
   AND TargetDay = CURDATE();
  </cfquery>
  <cfif checkTimecardQry.RecordCount NEQ 0>
   <cfreturn "本日は、既に出社打刻されています。">
  </cfif>
(C)

  <!--- タイムカードテーブルへ登録 --->
  <cfquery name="insertTimecardQry" datasource="NikkeiLinux">
I   NSERT INTO TimecardTable
   (
    UserID,
    TargetDay,
    ComingTime,
    QuittingTime
   )VALUES(
    '#arguments.userID#',
    CURDATE(),
    CURTIME(),
    NULL
   )
  </cfquery>
(D)

  <cfreturn "">
 </cffunction>
</cfcomponent>
ここでのポイントは次のとおりである。
(A) 未入力チェックを行う。
UserID、Passwordが未入力でないかチェックを行っている。
(B) UserID、Passwordが登録されたユーザのものであるかチェックを行う。
入力されたUserID、Passwordが登録ユーザのものであるか否かは、UserTableに該当するレコードが存在するか否かで判別可能だ。
(C) 対象日に既に出社打刻を行っていないかチェックを行う。
同一ユーザが既に出社打刻を行っているか否かは、対象ユーザ、対象日のレコードがTimecardTableに存在するか否かで判別可能だ。
(D) TimecardTableへデータを登録する。
全てのチェックが正常である場合は、TimecardTableテーブルへレコードを挿入する。
  2.4 その他の機能
    勤怠管理システムでは他にも以下のような機能を実装予定としている。
タイムカードの退社打刻機能
ユーザが入力した「UserID」、「Password」を基にユーザを特定し、退社記録を行う。
タイムカードの月次参照機能
ユーザの月別出退社時間を一覧表示する。
ユーザ情報更新機能
登録ユーザの情報を更新する。
ユーザ情報削除機能
登録ユーザの情報を削除する。
したがって、これらの機能を全て実装したColdFusionコンポーネントは、以下のようなものになる。

○「timecard」コンポーネント
提供メソッド commingStamp
処理概要 チェック結果が正常な場合、TimecardTableに出社打刻情報を登録する。
引数 UserID Password
戻値 エラーメッセージ
提供メソッド quittingStamp
処理概要 チェック結果が正常な場合、TimecardTableに退社打刻情報を登録する。
引数 UserID Password
戻値 エラーメッセージ
提供メソッド getTimecard
処理概要 チェック結果が正常な場合、TimecardTableに退社打刻情報を登録する。
引数 UserID 対象年 対象月
戻値 取得レコード

○「user」コンポーネント
提供メソッド userRegist
処理概要 UserTableに指定情報を登録する。
引数 UserID Password Name Email
戻値 エラーメッセージ
提供メソッド userListGet
処理概要 UserTableからユーザ一覧情報を取得し、取得データを返す。
引数 なし
戻値 クエリ
提供メソッド userDetailGet
処理概要 UserTableからユーザ詳細情報を取得し、取得データを返す。
引数 UserID
戻値 クエリ
提供メソッド userUpdate
処理概要 UserTableの特定Userの情報を更新する。
引数 UserID Password Name Email
戻値 エラーメッセージ
提供メソッド userDelete
処理概要 UserTableから特定Userの情報を削除する。
引数 UserID
戻値 -
各コンポーネントの詳細は、ここでは割愛させていただくが、付録にソースコードを含めているのでそちらを参照して欲しい。

いよいよ次回(最終回)は、今回作成した勤怠管理システムのバックオフィスと、FlashMXで作成したユーザインターフェースを連動させることでリッチインターネットアプリケーションへとグレードアップを行う予定である。

BACK  
PAGETOP
CLOSE