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

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

[鶴長鎮一,@IT]

 第9回「『オンラインストア』完成へ向けて各ファイルを再構築」までで、「簡易オンラインストア」の処理を一通り完成させましたが、今回はそこにAjax(Asynchronous JavaScript+XML)を取り入れ、フォーム入力を支援するよう改良を加えます。Ajaxを活用すれば、フォームボタンを押下に加え、キーボード入力やマウスのドラッグといったイベントをトリガーにして、ページ表示の一部だけを再描画することができます。

 前回までのシステムでは、郵便番号と住所への入力が互いに連携しておらず、個別に入力する必要がありました。今回はAjaxを用いて、郵便番号テキストボックスに数字が1文字入力されるごとに、入力された数字からデータベースを検索し、該当する住所が表示されるようにします。

 なお、Ajaxの基本や詳細については以下を参考にしてください。

関連記事:

古くて新しいAjaxの真実を見極める(@IT リッチクライアント&帳票)

http://www.atmarkit.co.jp/fwcr/special/ajax01/01.html

Ajax技術解説(@IT リッチクライアント&帳票)

http://www.atmarkit.co.jp/fwcr/index/index-wcr.html#ajax_review


サンプルファイルで理解するAjaxの動作

 「簡易オンラインストア」に改良を加える前に、Ajaxの簡単なサンプル「sample6」を基に解説しておきましょう(注)

注:なお、サンプルではフォーム入力値のチェックやMySQLサーバの設定など、セキュリティに対する考慮が不足しています。サンプルを使用する際は不特定のユーザーから利用されることがないよう、公開されたサーバ上での使用は控えるようにします。


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

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

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


サンプルダウンロード:

sample6のtarアーカイブ


 なお郵便番号・住所データベースには、日本郵政公社の「住所の郵便番号のダウンロードサービス」(読み仮名データの促音・拗音を小書きで表記したもの)を利用しています。日本郵政公社のデータをMySQLに取り込む方法については、コラム「郵便番号・住所データベースの作成方法」を参考にしてください(コラム1参照)

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

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

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


 インストール後、Webブラウザで「http://HTTPDサーバ/sample6/frontend.php」にアクセスし、動作を確認します。郵便番号テキストボックスに数字を入力するたびに、住所テキストボックスに該当する住所が表示され、同時にメッセージテキストエリアに該当件数が表示されていることを確認します。また住所検索の過程でデータベース接続エラーのような不具合が発生している場合は、メッセージテキストエリアにその内容が表示されます。

画面1 サンプルの動作確認(郵便番号を1けた入力するたびに、住所とメッセージが動的に変化する) 画面1 サンプルの動作確認(郵便番号を1けた入力するたびに、住所とメッセージが動的に変化する)

 最初の入力では、MySQLサーバ接続処理で多少反応が遅れる場合があります。その際は少し入力速度を抑え反応を確かめるようにします。

コラム1 郵便番号・住所データベースの作成方法

 sample6で使用している郵便番号・住所データベースでは、日本郵政公社の「住所の郵便番号のダウンロードサービス(読み仮名データの促音・拗音を小書きで表記したもの)」を利用しています。以下の手順により、公開されているCSVファイルから必要なデータだけをMySQLのデータとして取り込みます。

 まずhttp://www.post.japanpost.jp/zipcode/dl/kogaki.htmlから「全国一括」を選び、「ken_all.lzh」をダウンロードします。ファイルはLZH形式で圧縮されています。Linuxで解凍するには、別途lhaユーティリティが必要となるため、まずWindowsで解凍し、その後Linuxにファイルを転送するなどします。なおLinuxでlhaユーティリティを使用する場合は下記を参考にしてください。

関連記事:

Fedora Core 6でLZH形式の圧縮ファイルを展開するには
http://www.atmarkit.co.jp/flinux/rensai/linuxtips/986fc6lzh.html

Turbolinux 10 DesktopでLZH形式の圧縮ファイルを展開するには
http://www.atmarkit.co.jp/flinux/rensai/linuxtips/616uselzhtl.html


解凍後のファイル「KEN_ALL.CSV」の文字コードはシフトJISで、改行コードはCR+LFです。nkficonvコマンドを使用し、文字コードをUTF-8に変換します。なお変換後のファイルはMySQLデーモンで読み込みができるよう/tmpに作成し、以下のように読み込み権限を追加します。

# nkf -w KEN_ALL.CSV > /tmp/KEN_ALL_utf8.CSV
または、
# iconv -f SJIS -t UTF-8 -o /tmp/KEN_ALL_utf8.CSV KEN_ALL.CSV

MySQLデーモンで読み込みできるようother(o)に対し読み込み許可を与える(+r)
# chmod o+r /tmp/KEN_ALL_utf8.CSV

日本郵政公社のCSVデータには、不要なフィールドも含まれます。必要なデータは郵便番号(3番目のフィールド)と住所(7〜9番目のフィールドを連結したもの)だけです。Microsoft Excelなど、CSVを編集できるソフトを使ってデータを整形することもできますが、ここではMySQLを使ってデータを生成する方法を紹介します。

 まず、いったんこのファイルを、日本郵政公社のCSVファイルの全フィールドに1対1で対応するカラムを持った仮のテーブル「tmp_table」に読み込みます。その後、必要なカラムだけを本番テーブル「zip_address」へ吸い出します。作業手順は以下のとおりです。

データベース「sample_db6」を作成
   

仮のテーブル「tmp_table」を作成 (「CREATE TEMPORARY TABLE」クエリで仮テーブルを作成するため、mysqlクライアント終了とともに自動で削除される)
   

CVSデータを「LOAD DATA LOCAL INFILE」クエリを使ってtmp_tableへ読み込む
   

本番テーブル「zip_address」を作成 (検索優先のため、ストレージエンジンに「MyISAM」を指定)
   

tmp_tableテーブルの3番目のカラムデータと7〜9番目のカラムを結合し、作成したデータを「INSERT INTO ... SELECT」クエリを使ってzip_addressテーブルに取り込む


データベース「sample_db6」を作成
# mysqladmin -uroot -p create sample_db6

データを加工するための仮のテーブル「tmp_table」を作成。「CREATE TEMPORARY TABLE」クエリを使用しているため、mysqlクライアント終了とともにtmp_tableテーブルは自動で削除される
# mysql -uroot -p sample_db6
mysql> CREATE TEMPORARY TABLE `tmp_table` (
    -> `c1` text,
    -> `c2` text,
    -> `c3` text,
    -> `c4` text,
    -> `c5` text,
    -> `c6` text,
    -> `c7` text,
    -> `c8` text,
    -> `c9` text,
    -> `c10` text,
    -> `c11` text,
    -> `c12` text,
    -> `c13` text,
    -> `c14` text,
    -> `c15` text
    -> ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.00 sec)

「LOAD DATA LOCAL INFILE」クエリを使って「/tmp/KEN_ALL_utf8.CSV」を取り込む。下記オプションでCSVのフォーマットを指定する
     FIELDS
             TERMINATED BY ',' :区切り文字「,」
             ENCLOSED BY '"' \ :フィールド囲み「"」
     LINES
             TERMINATED BY '\r\n':レコード改行「CR(\r)+LF(\n)」
mysql> LOAD DATA LOCAL INFILE '/tmp/KEN_ALL_utf8.CSV' INTO TABLE tmp_table \
    -> FIELDS TERMINATED BY ',' ENCLOSED BY '"' \
    -> LINES TERMINATED BY '\r\n';
Query OK, 121960 rows affected (3.63 sec)
Records: 121960 Deleted: 0 Skipped: 0 Warnings: 0

本番テーブル「zip_address」を作成。郵便番号カラムには重複を許さないプライマリインデックスではなく、重複データを許容する非ユニークインデックスを使用する。検索速度を向上させるためストレージエンジンに「MyISAM」を指定し、各カラムのサイズも適切なものを使用している
mysql> CREATE TABLE `zip_address` (
    -> `zip` varchar(7) NOT NULL,
    -> `address` varchar(100) NOT NULL,
    -> KEY `key_zip` (`zip`)
    -> ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.01 sec)

「INSERT INTO ... SELECT」クエリを使って、tmp_tableテーブルの3番目のカラムデータと、7〜9番目のカラムを結合したデータをそれぞれzip_addressテーブルに取り込む。カラムデータの文字連結にはMySQLのconcat()関数を利用する
mysql> INSERT INTO zip_address SELECT c3,concat(c7,c8,c9) FROM tmp_table;
Query OK, 121960 rows affected (1.71 sec)
Records: 121960 Duplicates: 0 Warnings: 0

 最後に、一連のデータがzip_addressに正常に登録されているかどうかを確認します。データ件数は12万1960件に及ぶため、LIMIT節を用いて出力数を抑制することを忘れないようにします。

mysql> select * from zip_address limit 10;
+---------+-------------------------------------------------+
| zip     | address                                         |
+---------+-------------------------------------------------+
| 0600000 | 北海道札幌市中央区以下に掲載がない場合          |
| 0640941 | 北海道札幌市中央区旭ケ丘                        |
| 0600041 | 北海道札幌市中央区大通東                        |
| 0600042 | 北海道札幌市中央区大通西(1〜19丁目)        |
| 0640820 | 北海道札幌市中央区大通西(20〜28丁目)      |
| 0600031 | 北海道札幌市中央区北一条東                      |
| 0600001 | 北海道札幌市中央区北一条西(1〜19丁目)      |
| 0640821 | 北海道札幌市中央区北一条西(20〜28丁目)    |
| 0600032 | 北海道札幌市中央区北二条東                      |
| 0600002 | 北海道札幌市中央区北二条西(1〜19丁目)      |
+---------+-------------------------------------------------+
10 rows in set (0.01 sec)


       1|2|3 次のページへ

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

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

メールマガジン登録

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