連載
» 2007年08月24日 00時00分 公開

今から始める MySQL入門(10):AjaxのバックエンドにPHP+MySQL (3/3)

[鶴長鎮一,@IT]
前のページへ 1|2|3       

フロントエンド(frontend.html、frontend.js)の処理

 フロントエンドのfrontend.htmlの5行目で、外部のJavaScriptファイルfrontend.jsを読み込みます。JavaScriptを外部ファイル化することで、HTMLファイルのヘッダー部(<HEAD>〜</HEAD>)を簡素化できます。

 入力フォーム(16〜38行目)では、name属性でform1を指定しておきます(16行目)。同様に各テキストボックスやテキストエリアにもname属性で固有の識別子を割り当てておきます(212732行目)。固有の識別子を割り当てることで、テキストエリアに入力された値の操作などを、容易にJavaScriptから行えるようになります。

 郵便番号テキストボックスではキー入力(具体的には、押下したキーが解放された瞬間)をトリガーに、JavaScriptで定義したsetZip_code()関数を実行するよう、イベント属性「onkeyup」にsetZip_code()関数を指定します。その際、「this.value」で得られるテキストボックスへの入力値をsetZip_code()の引数として渡します(21行目)。なおキー入力がトリガーになるため、setZip_code()の実行頻度は高くなっています。

 バックエンドのメッセージを表示するメッセージテキストエリアは、表示のみのため、readonly属性を付加します(32行目)。

5 <script type="text/javascript" src="frontend.js"></script>

16 <form name="form1">

20 <td>〒番号:</td>
21 <td><input type=text name="zip_code" size="7" maxlength="7" onkeyup="setZip_code(this.value)">

26 <td>住所 :</td>
27 <td><input type=text name="address" size="50" maxlength="100"></td>

31 <td>メッセージ:</td>
32 <td><textarea name="mess" cols="45" rows="4" readonly></textarea></td>

38 </form>
      リスト2 frontend.html

 Ajaxのフロントエンド処理を担うfrontend.jsは、大まかに以下のような処理で構成されています。

JavaScriptでHTTP通信を行うためのXMLHttpRequestオブジェクトを生成する(2行目)(ブラウザ別に生成方法を用意(47〜74行目))
    

バックエンドへのリクエストURL「backend.php?zip_code=郵便番号テキストボックスに入力された値」を作成(8行目
    

XMLHttpRequestオブジェクトのopen()メソッドで、HTTPメソッド(GET)/リクエストURL/非同期の使用(true)を設定する(9行目)。
    

バックエンドからデータを受信する際にコールバック関数が実行されるよう、XMLHttpRequestオブジェクトのonreadystatechangeプロパティにコールバック関数を設定する。レスポンスデータの処理はコールバック関数で行う(12行目
    

XMLHttpRequestオブジェクトのsend()メソッドでサーバへリクエストを送信する(15行目


 1 //XMLHttpRequestオブジェクト生成
 2 var xmlHttp = createXmlHttpRequest();
 4 //郵便番号テキストフィールドのonkeyupイベントで実行される処理。リクエストを生成し、レスポンスを取得
 5 function setZip_code(zip_code){
...
 8   var url = 'backend.php?zip_code='+zip_code;
 9   xmlHttp.open('GET', url, true);
...
12   xmlHttp.onreadystatechange = handleHttpEvent;
...
15   xmlHttp.send(null);
16 }

18 //HTTPレスポンスデータを処理し、XMLを解析しフォームに値をはめ込むコールバック関数
19 function handleHttpEvent(){
...
44 }
46 //ブラウザ別にXMLHttpRequestオブジェクトを生成
47 function createXmlHttpRequest(){
...
74 }
      リスト3-1 frontend.js

 さらに、バックエンドからデータを受信したときに呼び出されるコールバック関数「handleHttpEvent」では、以下のような処理が行われます。

XMLHttpRequestオブジェクトのreadyStateプロパティを使って、受信データが読み込み済み(4)か確認し、同時にstatusプロパティでHTTPレスポンスコードが正常(200)であることを確認する。正常性を確認できたとき、この後の処理を行う(21行目
    

XMLHttpRequestオブジェクトのresponseXMLプロパティで、サーバからのレスポンスをXMLDocumentオブジェクトとして取得(24行目
    

取得したXMLDocumentオブジェクトからgetElementsByTagName("要素名")を使ってXMLの各要素を取り出す。まず「<stat>〜</stat>」から値を取り出し、「ok」ならば住所データと該当件数を取り出し、各テキストボックス・エリアに当てはめる(29〜35行目)。「na」ならメッセージだけを取り出してメッセージテキストエリアに当てはめ、住所テキストボックスの内容はクリアする(36〜41行目


19 function handleHttpEvent(){
...
21   if (xmlHttp.readyState == 4 && xmlHttp.status == 200){
...
24     var xmlDoc = xmlHttp.responseXML;
25     if (xmlDoc.documentElement){
...
29       if (stat.data == "ok"){
...
36       }else if(stat.data == "na"){
...
41       }
42     }
43   }
44 }
      リスト3-2 frontend.js

サンプル利用時の注意

 以上がバックエンドとフロントエンドの処理内容になります。

 なお、作成過程でJavaScriptやバックエンドを修正したにもかかわらず、ブラウザの表示結果に反映されない場合があります。AjaxもHTTPリクエストを使用する以上、非同期で取得するデータにもブラウザのキャッシュが使用されます。特に、GETメソッドを使用し、しかもURLに変化がない場合は、キャッシュヒット率が高くなります。

 また、データベースのデータ、HTMLやPHPファイルのエンコード、バックエンドから送出されるXML、すべての文字コードをUTF-8に統一しています。文字化けが発生するようなら、php.iniに以下の2行を追加しておきます。php.iniのインストール先は第1回「MySQL+Apache+PHPをインストールしよう」を参考にしてください。

[mbstring]
mbstring.internal_encoding = UTF-8
mbstring.http_output = UTF-8
※使用はmbstringが有効な場合に限られます。mbstringについては第1回「MySQL+Apache+PHPをインストールしよう」を参照

コラム2 XMLパースエラーとその対策

 ブラウザからの動作確認で、バックエンドへ直接アクセスしXMLを表示しようとした際、画面4のように「XMLパースエラー」が表示され、正常な動作が確認できない場合があります。これは、エラー内容のとおり「」が先頭になく、スペースや改行などの不正文字が挿入している場合に発生します。

画面4 XMLパースエラー(Firefoxの場合) 画面4 XMLパースエラー(Firefoxの場合)

 これを防ぐにはPHPファイルを確認し、特に、<?php ...?>前後に無駄な改行や空白がないようにします。また直接XMLを出力するPHPとは別に、require_onceなどで外部ファイルを読み込んでいる場合は、そのPHPファイルに無駄な改行や空白がないか確認します。

        ←ここにスペースや改行が挿入されていないか確認する
<?php
...
?>
        ←requireで読み込まれるファイルでは、ここにスペースや改行が挿入されていないかも確認する

「簡易オンラインストア」にAjaxを組み込む

 sample6で作成したAjaxによる住所データ入力支援機能を、前回までに作成した「簡易オンラインストア」に組み込みます。

PHPファイル改修のポイント

 前回作成したsample5に先ほどのsample6を統合しますが、その際、DTO・DAOパターンを踏襲するよう改修を加えます。

 Ajaxのバックエンドを担うbackend.phpでは、MySQL接続・切断・データ抽出といったDB操作を、新たに作成するZip_addressDao.phpに分離します。それに伴いZip_address.phpを作成し、DTOに利用します。frontend.jsはほぼそのまま使用しますが、メッセージテキストエリアがないため、関連する処理を削除します。frontend.jsを読み込む1行を、ユーザーに住所入力を促すconfirm.phpに追加します。

 PHPファイルの改修は以上です。最後に、sample6と同様に、郵便番号・住所データをMySQLに用意します。

sample7のインストールと動作確認

 こちらからサンプルアーカイブ「sample7.tgz」をダウンロードし、Apache HTTPDのドキュメントルート(注)など、PHPが動作するディレクトリに展開し、作業ディレクトリを移動します。その後サンプルに含まれる「sample_db7.sql」を利用し、データベース「sample_db7」を準備します。

注:ソースからデフォルトインストールした場合は/usr/local/apache2/htdocs、FedoraやRed hatなどRPMインストールした場合は/var/www/htmlなど


サンプルダウンロード:

sample7のtarアーカイブ


サンプル「sample7」をドキュメントルートに展開し、作業ディレクトリを移動する。下のドキュメントルートはFedoraやRed hatなどRPMインストールした場合の例。適宜変更する
# cd /var/www/html
# tar xvfz /..pathto../sample7.tgz
# cd sample7

データベース「sample_db7」を作成する
# mysqladmin -u root -p create sample_db7

「sample_db7.sql」ファイルで各テーブルと初期データを準備する。権限設定(ユーザー名:php、パスワード:password)も同時に行われる。ただしApache HTTPDサーバとMySQLサーバが同一ホストでない場合は、新たな権限の追加が必要になる。その場合の作業は、第8回の「sample5のインストール手順と確認作業」を参考にする
# mysql -u root -p sample_db7 < sample_db7.sql

 インストール後の確認作業として、まずmenu.phpを表示させ、商品を購入します。その後表示されるconfirm.phpの「〒番号」に数字を入力し、住所欄に自動的にデータが挿入されることを確認します。なお、最初の入力では、MySQLサーバ接続処理のために多少反応が遅れる場合があります。その際は少し入力速度を抑え、反応を確かめるようにします。


 以上、Ajaxを取り入れ、PHPをバックエンドに使用する方法を紹介しました。

 セッションステートレスなHTTPでは、画面の切り替わりに伴い入力データを引き継がせる処理が煩雑になるため、ネイティブアプリケーションのような入力支援機能を取り入れるには、大変な苦労が伴います。しかしこのようにAjaxを使用することで、画面遷移に関係なく、ユーザーインターフェイスを充実させることができます。

 ただし、その分バックエンドに掛かる負荷は高くなります。今回のサンプルのように、キー入力が発生するたびにデータベースへの問い合わせが発生するようなケースでは、別途データベースとの接続を最適化させる手段を検討するようにしてください。(次回に続く)

【参考】

KJ(著)、田中 ナルミ(著)

「PHPによるWebアプリケーションスーパーサンプル 活用編」

ソフトバンククリエイティブ



前のページへ 1|2|3       

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。