ObjectSquare [2002 年 2 月号]

[技術情報]





PHP4+PostgreSQL7 で構築する Web-DB 入門

第 3 回【最終回】 〜 PHP と PostgreSQL は仲良し〜


株式会社オージス総研
マーケティング企画部
山井 智博
▼ 目次
1.はじめに。
2.前回のつづき。
3.PHP の PostgreSQL 関数。
4.「ハイパー住所録」要件定義。
5.「ハイパー住所録」画面遷移。
6.「ハイパー住所録」ソースコード。
7.ソースコードの解説。
8.おわりに。


■ 1. はじめに。

あけまして、おめでとうございます。

早いもので、2001 年も気づけばあっという間に過ぎ去ってしまった気がします。
米国同時多発テロ、報復戦争と、あまり良いニュースはなかったような感もありますが、今年が皆様にとって(もちろん、私にとっても)、実りある年であることを切に願います。
(追補)12/1、皇太子妃雅子さまご出産という喜ばしいニュースがありました。おめでとうございます。

さて、これまで 2 回の連載にわたり、「第 1 回〜スクリプト言語PHP編〜」「第 2 回〜PostgreSQL編〜」と、PHP 言語とデータベース PostgreSQL についてご紹介させていただきました。

最終回である今回は、実際に PHP と PostgreSQL を使用して、簡単な住所録アプリケーション「ハイパー住所録」を作成してみたいと思います。
あまりにも簡単に Web-DB アプリケーションを作成できることに、きっと驚かれるのではないでしょうか。

それでは、今回も元気に行きましょう。

Happy Scripting !! (2001/12/3)


■ 2. 前回のつづき。

前回は、PostgreSQL の特徴について説明させていただきました。

また、そこで「test」データベースを作成し、「address_book」テーブルを作成しました。覚えていらっしゃいますか?
ちなみに、「address_book」のスキーマは、

アドレス帳

のとおりです。

それでは、実際に作成した、「address_book」テーブルを見てみましょう。

test=> \d address_book
      Table "address_book"
  Attribute   | Type | Modifier
--------------+------+----------
 name         | text |
 address      | text |
 phone_number | text |

test=> SELECT * FROM address_book ;
           name           |                  address                  | phone_number
--------------------------+-------------------------------------------+--------------
 ヤマイ@カリスマ末端社員 | 新潟県刈羽郡小国町チャーザー村 ニコニコ寮 | 12-3456-7890
(1 row)

次章以降、この「test」データベースを使用した、住所録アプリケーションを作成しながら説明を進めたいと思います。

なお、前回に引き続き、ソフトウェアは
▼ PHP4.0.5
▼ PostgreSQL7.1.2
を使用します。



■ 3. PHPのPostgreSQL関数。

さて、連載第 1 回にて、PHP の特徴として「多彩なデータベースをサポートし、それらを扱う関数群が豊富である」と述べました。
PHP は、PostgreSQL に関する関数も多数提供しています。

この章では、主に使用する PostgreSQL 関数についてご説明したいと思います。

pg_connect() 関数
PostgreSQLコネクションを開く

PostgreSQL のデータベースに接続し、データベース・ハンドルを返します。
また、接続に失敗した場合は FALSE を返します。
# 成功の場合と失敗の場合で、返り値の型が違うのは、気持ち悪いですね、、

【使用例】
$dbHandle = pg_connect("host=localhost port=5432 dbname="database");
pg_close() 関数
PostgreSQLコネクションを閉じる

PostgreSQL のデータベースとの接続を、切断します。
引数として渡されたデータベース・ハンドルが、有効なコネクションの場合は TRUE を、そうでなければ FALSE を返します。

【使用例】
$result = pg_close($dbHandle);
pg_exec() 関数
クエリーを実行する

引数で渡されたクエリーを実行します。
クエリーが成功した場合、問い合わせ結果を、クエリーに失敗した場合 FALSE を返します。

【使用例】
$resultSet = pg_exec($dbHandle,"SELECT * FROM table");
pg_numrows() 関数
問い合わせ結果の行数(レコード数)を取得する

pg_exec() で取得した問い合わせの結果を調査し、その行数(レコード数)を返します。

【使用例】
$resultNum = pg_numrows($resultSet);
pg_fetch_object() 関数
問い合わせ結果の行を、オブジェクトとして取得する

取得した行に対応する属性を有するオブジェクトを返します。
つまり、1レコードを、オブジェクトの形で返すことになります。

【使用例】
$obj = pg_fetch_object($resultSet, $count);


以上が、主に使われる(と思われる)PHP の PostgreSQL 関数になります。
これらの関数で、大抵のデータベース操作は可能だと考えています。

実際、私はこれ以外の PostgreSQL 関数を使用したことがありません(あまり自慢できることではないですが)。


■ 4.「ハイパー住所録」要件定義。

さて、それでは「ハイパー住所録」の要件定義に入ることにしましょう。

問題領域をよりわかりやすくするために、今回は下図の 2 ユースケースのみを対象とすることにします。

ユースケース図


ユースケース「住所録を閲覧する」
ユーザは、Web ブラウザを使用し、システムを利用する。
ユーザが、「住所録を閲覧する」ボタンを押下すると、Web ブラウザ上にデータベースに登録されている住所(具体的には、名前、住所、電話番号)が一覧表示される。

ユースケース「住所を登録する」
ユーザは、Web ブラウザを使用し、システムを利用する。
ユーザが、「住所を登録する」ボタンを押下すると、Web ブラウザ上に名前、住所、電話番号を入力するためのテキストフィールドが表示される。
ユーザが、必要事項を入力し、「登録」ボタンを押下すると、データはデータベースに登録され、Web ブラウザ上に、登録されている住所の一覧が表示される。

それでは、早速、実装に入ってしまいましょう。


■ 5. 「ハイパー住所録」画面遷移

以下が、実装された「ハイパー住所録」の画面になります。

まずは、メニュー画面。
なげやりな感じが、「ハイパー」ですね。

ハイパー・メニュー画面

ここで、「住所を登録する」ボタンを押下すると、こんなフォームが表示されます。

データ入力用フォーム

ここで、登録ボタンを押下すると、データがデータベースに登録されます。

それでは、実際に登録されたデータを見てみましょう。
「住所録を閲覧する」ボタンを押下します。

住所録の閲覧

前回、INSERT したレコード、そして、今フォームで入力したレコードが表示されていますね。

以上が、「ハイパー住所録」の画面遷移になります。


■ 6.「ハイパー住所録」ソースコード

 1  <HTML>
 2  <BODY>
 3 
 4  <BR>
 5  <B>ハイパー住所録</B><BR>
 6  <BR>
 7 
 8  <!-- メニューを表示する -->
 9  ▼ メニュー<BR>
 10 <FORM ACTION="address_book.php" METHOD="post">
 11 <INPUT TYPE="submit" VALUE="住所録を閲覧する" NAME="btn"> 
 12 <INPUT TYPE="submit" VALUE="住所を登録する" NAME="btn">
 13 </FORM>
 14 <BR>
 15 
 16 <!-- PHP スクリプト開始 -->
 17 <?php
 18 
 19 /**
 20  * メイン部 押下されたボタンによって、処理を振り分ける
 21 **/

 22 switch($btn) {
 23 case "住所録を閲覧する":
 24   printAddressBook();
 25   break;
 26 
 27 case "住所を登録する":
 28   print printInsertForm();
 29   break;
 30 
 31 case "登録":
 32   insertAddressRec($name,$address,$phoneNumber);
 33   break;
 34 }
 35 
 36 exit();
 37 
 38 /**
 39  * データベースに接続する
 40 **/

 41 function connectDb() {
 42 
 43   $dbHandle = pg_connect("host=localhost port=5432 dbname=test");
 44 
 45   if($dbHandle == FALSE) {
 46     // エラー処理
 47   }
 48 
 49   return $dbHandle;
 50 }
 51 
 52 /**
 53  * データベースとの接続を切断する
 54 **/

 55 function disconnectDb( $dbHandle ) {
 56 
 57   $result = pg_close($dbHandle);
 58 
 59   if($result == FALSE) {
 60     // エラー処理
 61   }
 62 }
 63 
 64 /**
 65  * SQLを実行する
 66 **/

 67 function execSql($dbHandle, $sql) {
 68 
 69   $resultSet = pg_exec($dbHandle,$sql);
 70 
 71   if($resultSet == FALSE) {
 72     // エラー処理
 73   }
 74   return $resultSet;
 75 }
 76 
 77 /**
 78  * アドレス帳の内容を表示する
 79 **/

 80 function printAddressBook() {
 81 
 82   // データベースに接続する
 83   $dbHandle = connectDb();
 84 
 85   // テーブル address_book より、全レコードを抽出するクエリー
 86   $sql = "SELECT * FROM address_book";
 87 
 88   // クエリーを実行する
 89   $resultSet = execSql($dbHandle,$sql);
 90 
 91   // データベースとの接続を切断する
 92   disconnectDb($dbHandle);
 93 
 94   // 検索結果のレコード数を取得する
 95   $resultNum = pg_numrows($resultSet);
 96 
 97   $i = 0;
 98 
 99   // テーブルを表示する
100   print "<TABLE BORDER=\"1\">";
101
102  while($i < $resultNum) {
103
104     // レコードをオブジェクトとして取得する
105     $rec = pg_fetch_object($resultSet,$i);
106
107     print "<TR>";
108     print "<TD>$rec->name</TD>";
109     print "<TD>$rec->address</TD>";
110     print "<TD>$rec->phone_number</TD>";
111     print "</TR>";
112
113     $i++;
114   }
115
116   print "</TABLE>";
117 }
118
119 /**
120 * レコード追加用のフォームを表示する
121 **/

122 function printInsertForm() {
123
124   print "データを入力して下さい。<BR>";
125
126   print "<FORM ACTION=\"address_book.php\" METHOD=\"post\">";
127   print "名前: <INPUT TYPE=\"text\" NAME=\"name\"><BR>";
128   print "住所: <INPUT TYPE=\"text\" NAME=\"address\"><BR>";
129   print "電話: <INPUT TYPE=\"text\" NAME=\"phoneNumber\"><BR><BR>";
130   print "<INPUT TYPE=\"submit\" VALUE=\"登録\" NAME=\"btn\">";
131   print "</FORM>";
132 }
133
134 /**
135 * 新規にレコードを登録する
136 **/

137 function insertAddressRec($name,$address,$phoneNumber) {
138
139   // データベースに接続する
140   $dbHandle = connectDb();
141
142   // 新規にレコードを登録するクエリー
143   $sql = "INSERT INTO address_book VALUES('$name','$address','$phoneNumber')";
144
145   // クエリーを実行する
146   execSQL($dbHandle,$sql);
147
148   // データベースとの接続を切断する
149   disconnectDb($dbHandle);
150
151   // 全レコードを表示する
152   printAddressBook();
153 }
154
155 ?>
156
157 </BODY>
158 </HTML>


■ 7.ソースコードの解説。

それでは、「ハイパー住所録」のソースコードを、簡単に解説してみたいと思います。

まずは、以下の部分。

 8  <!-- メニューを表示する -->
 9  ▼ メニュー<BR>
 10 <FORM ACTION="address_book.php" METHOD="post">
 11 <INPUT TYPE="submit" VALUE="住所録を閲覧する" NAME="btn"> 
 12 <INPUT TYPE="submit" VALUE="住所を登録する" NAME="btn">
 13 </FORM>
 14 <BR>
 15 
 16 <!-- PHP スクリプト開始 -->
 17 <?php
 18 
 19 /**
 20  * メイン部 押下されたボタンによって、処理を振り分ける
 21 **/

 22 switch($btn) {
 23 case "住所録を閲覧する":
 24   printAddressBook();
 25   break;
 26 
 27 case "住所を登録する":
 28   print printInsertForm();
 29   break;
 30 
 31 case "登録":
 32   insertAddressRec($name,$address,$phoneNumber);
 33   break;
 34 }

入力ボタンに「btn」という名前をつけています(11,12行)。
このボタンが押下されると、変数 $btn に、入力ボタンの VALUE(例:住所録を閲覧する)が格納されます。

そして、22行の swich 文で、押下されたボタンによって処理を振り分けているわけですね。

こういった処理は、PHP のアクション処理の常套手段となります。


次に、実際にデータベースにアクセスし、値を取り出す処理を見てみましょう。

 77 /**
 78  * アドレス帳の内容を表示する
 79 **/

 80 function printAddressBook() {
 81 
 82   // データベースに接続する
 83   $dbHandle = connectDb();
 84 
 85   // テーブル address_book より、全レコードを抽出するクエリー
 86   $sql = "SELECT * FROM address_book";
 87 
 88   // クエリーを実行する
 89   $resultSet = execSql($dbHandle,$sql);
 90 
 91   // データベースとの接続を切断する
 92   disconnectDb($dbHandle);

まず、関数 connectDb()によってデータベースハンドルを取得し(83行)、クエリーを発行しています(89行)。
クエリーの実行結果は、変数 $resultSet に格納されます。

$resultSet の各レコードを抽出するのが、以下の処理です。

 94   // 検索結果のレコード数を取得する
 95   $resultNum = pg_numrows($resultSet);
 96 
 97   $i = 0;
 98 
 99   // テーブルを表示する
100   print "<TABLE BORDER=\"1\">";
101
102  while($i < $resultNum) {
103
104     // レコードをオブジェクトとして取得する
105     $rec = pg_fetch_object($resultSet,$i);
106
107     print "<TR>";
108     print "<TD>$rec->name</TD>";
109     print "<TD>$rec->address</TD>";
110     print "<TD>$rec->phone_number</TD>";
111     print "</TR>";
112
113     $i++;
114   }
115
116   print "</TABLE>";

まず、関数 pg_numrows() で $resultSet に格納されているレコード数を取得します(95行)。

次に、$resultSet に格納されているレコードを、オブジェクトとして、イテレーティブに取得しています(105行)。
オブジェクトの属性は、テーブルの各カラム(列)に対応しており、アロー演算子( -> )でアクセスすることが可能です(108〜110行)


■ 8. おわりに。

いかがだったでしょうか?

PHPとPostgreSQLを使用し、いかにお手軽に Web-DBアプリケーションを構築することができるかについて、お解りになったかと思います。
これも、PHP が Webサイトを構築するために開発された言語であること、また、豊富な PostgreSQL 関数を標準で提供していることに尽きるかと思います。

Web-DB アプリケーションを構築する上で、この組み合わせがベストであるとは言いませんが、ひとつの解として、頭の片隅に置いていただければ幸いです。

さて、全 3 回の連載も、これで終了です。
全体を通し、PHP、そして PostgreSQL の魅力について、うまくお伝えすることができたでしょうか。

本当のところ、最終回では永続オブジェクトをいかに RDBMS のテーブルにマッピングするか、また責務の割り当て、そしてよく使用される構造(パターン)についてお話しようかと思っていたのですが、調べていくうちに様々なアプローチが存在するようで(正直なところ、当初、こういった話題は既に枯れた話題だと思っていました)、これについては(要望が多ければ)またの機会にご紹介させていただこうかと考えています。

この連載中、いろいろなご意見、励ましのお言葉をいただいた方々に感謝します。
それでは、またお目にかかりましょう。

adios !!


▼ 参考文献
『PC UNIXユーザのための PostgreSQL完全攻略ガイド』 技術評論社 1999年
『PHP4でカンタンWebDB構築ガイド』 秀和システム 2001年
▼ 参考リンク
PostgreSQL 本家(英語)
日本 PostgreSQL ユーザ会
PostgreSQL 7.1.3 ドキュメント
PHP 公式Webサイト(英語)
日本 PHP ユーザ会
Apache 公式Webサイト(英語)




記事の内容を5点満点で評価してください。
1点 2点 3点 4点 5点
記事に関するコメントがあれば併せてご記入ください。
  



© 2002 OGIS-RI Co., Ltd.
Prev. Index
Prev. Index