2-5
Webサーバを利用したデータベースアクセス
1 目的 PHPと呼ばれるスクリプト言語を利用し,PostgreSQLのデータベースをWeb上で操作し,デー タベースに追加,削除,変更等を行い,Webサーバを利用したデータベースアクセスの基礎的 な知識や技術を習得する。 2 使用機器及びソフトウェアWindowsXPのクライアントパソコン Linux(Fedora Core3)のサーバパソコン PostgreSQL PHP
3 関連知識
Webサーバを利用したデータベースアクセスをするためには,通常,二つの手法がある。 (1) Webサーバ側での実現方法
① CGI(Common Gateway Interface)
Webサーバの設定によって,HTMLに記述されたプログラムをサーバ側で実行し,実行結果 をブラウザに送信する方法である。実行するプログラムは,通常,Perl,C言語またはUNIX シェルスクリプトなどが使われる。 ② スクリプト言語(ミドルウェア方式) Webページに,Webサーバが解釈可能なスクリプトを埋め込む形でHTMLを統合化する方法で ある 「PHP(Hypertext Preprocessor)」はWebサーバで実行され,結果のHTMLファイルのみ。 をクライアントへ送信する 「JSP(Java Server Pages。 )」も同様の機能を持っている。
, , 。 また Webサーバで実行するので 動作結果がブラウザの種類やバージョンに依存しない (2) ブラウザ側での実現方法 ① JavaScript Netscape社が同社のNavigatorのために開発したブラウザ側のスクリプト言語である。 次に述べるJavaと一緒に解説されることが多いが,Java Appletを作成する言語とは異な る仕様である。JavaScriptは,簡単な画面制御に向いている言語である。 ② Java Sun Microsystems社の提唱によるオブジェクト指向言語である。ブラウザが動作している プラットホーム(UNIXか,Windowsか,Macかということ。)に依存しないプログラム実行環境 の実現が可能となる言語である。 Webサーバが利用できるのは,HTML形式で記述されたテキストであり,ブラウザから送信 される「利用者の回答」に応じて処理の流れを変えることは,一般には不可能である。 また,Webサーバは 「利用者の要求」に応じてデータベースにアクセスする方法も持ち合, わせていない。こうした処理を可能にするのが,スクリプト言語のPHPである。 例えば,図1の不動産のページについて考えると,1万件の物件があったとすると,個々
の物件紹介ページをHTMLで作成すると1万ページ必要になる。PHPなどのスクリプトをHTML に組み込むと,データベースから動的に物件紹介ページを生成することができるので,デー タベースと1ページ分のスクリプトで済む。作成するときの手間だけでなく,変更があった ときの手間も考えると,データ数が多ければ多いほど動的に作成されるページは威力を発揮 する。 図1 HTMLとPHPの違い HTMLの場合 PHPの場合 , , , PHPは HTML中にスクリプトとして直接記述できるため データベースのアクセスに関して PostgreSQLを利用するための関数が用意されており,Webページから簡単にPostgreSQLのデー タベースに接続することができる。WebサーバとDBサーバの連携を利用したWebページ閲覧の 概要を図2に示す。 図2 WebサーバとDBサーバの連携を利用したWebページの閲覧
1000.html
10000.html
1000.html
データ分の ページ数view.php?id=10000
物件データベース
データベースと スクリプト1ページWebサーバの設定ファイルを編集し,スクリプト機能を構築する。 Webサーバへの「PHPス クリプト」機能の構築手順 を図3に示す。 図3 Webサーバへの「PHPスクリプト」機能の構築手順 (1) データベース管理者の登録 (2) 設定ファイルの編集 (httpd.conf) (3) Apacheの再起動と動作確認 (4) PHPスクリプトの作成 (5) クライアント(WindowsXP)からの確認
4 実習 【例題】 PHPスクリプトを使い,データベース「testdb」のテーブル「table1」を取り込み,1 ぺージに5件のデータ表示させるWebサーバを構築する。さらに,データを追加できるWeb サーバを構築する。クライアント(WindowsKP)のブラウザからそれぞれのWebサーバのURL 「epc**.cen.hic.ac.jp/5kenzutu.php」(図4),「epc**.cen.hic.ac.jp/tuika.php」(図5) を入力し,確認する。 図4 epc**.cen.hic.ac.jp/5kenzutu.php 図5 epc**.cen.hic.ac.jp/tuika.php (1) データベース管理者の登録 ① ユーザ「nobody」の登録 データベース管理者としてユーザ「nobody」を登録する (ユーザ「postgres」は,イン。 ストール時に登録されている )。 ・空いている画面で右クリックし [端末を開く]を選択する。, ・次のように入力し,それぞれ Enter キーを押す。 ユーザIDを「postgres」に変更する。 n データベース管理者「nobody」を登録する。 o ユーザIDを「root」に戻す ( Ctrl キーと D キーを同時に押す ) p 。 。 su postgres [root@epc** root]# createuser bash-3.00$ nobody Enter name of user to add:
y Shall the new user be allowed to create databases? (y/n)
n Shall the new user be allowed to create more new users? (y/n) CREATE USER [Ctrl]+[D] bash-3.00$ [root@epc** root]# ② ディレクトリの作成 ・ 端末]に次のように入力し,それぞれ Enter[ キーを押す。 「 」 n ユーザIDを postgres に変更する。 データベース管理者 o 「nobody」を登録する。 ユーザIDを「root」 p に戻す。
cd /home/wwwadmin [root@epc** root]# mkdir www [root@epc** wwwadmin]# (2) 設定ファイルの編集 (httpd.conf) 設定ファイル(フォルダ「/etc/httpd/conf」のファイル「httpd.conf」を編集する。 ① ファイル「httpd.conf」のバックアップ(httpd.conf.orig2) ・ 端末]に次のように入力し,それぞれ Enter[ キーを押す。 cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.orig2 [root@epc** root]# ② geditの起動 図6 編集画面 ・ アプリケーション]から[アクセサ[ リ],[GNOMEテキスト・エディタ]をク リックする。 ③ ファイルの表示 ・図6の[ファイル]より[開く]を選 択する。 ・ ファイルシステム]をダブルクリッ[ クする。 ・フォルダ名「/etc/httpd/conf ,フ」 ァイル名「httpd.conf」を選択し,ダ ブルクリックする。 ・ 検索]より[検索]を選択する。[ ④ 「httpd.conf」ファイルの編集 ・次のように「httpd.conf」ファイルを編集する ( #」はコメント文である )。「 。 サーバ管理者のメールアドレス(wwwadmin@epc**.cen.hic.ac.jp)を設定する。 n (検索する文字列に「ServerAdmin」を入力し [検索]ボタンを3回クリックする ), 。 データベース管理者のユーザ,グループを設定する。 o (検索する文字列に「user apache」を入力し [検索]ボタンをクリックする ), 。 Webサーバのホスト名(epc**.cen.hic.ac.jp)を設定する。 p (検索する文字列に「ServerAdmin」を入力し [検索]ボタン3回クリックする ), 。 DocumentRoot(/home/wwwadmin/www)を設定する。 q (検索する文字列に「DocumentRoot」を入力し [検索]ボタンを2回クリックする ), 。 UserDirを確認する。 r (検索する文字列に「UserDir」を入力し [検索]ボタンを7回クリックする ), 。 DirectoryIndexを設定する。 s (検索する文字列に DirectoryIndex を入力し「 」 ,[検索 ボタンを2回クリックする] 。) 指定したディレクトリのインデックスファイルを指定及び追加できる。 directoryを設定する。 t
(検索する文字列に「Directory」を入力し [検索]ボタンを10回クリックする ), 。 使用するdirectoryの設定を記述する。ここではドキュメントルートディレクトリと 同じにする。 PHPファイルの認識を設定する。 u (検索する文字列に「addtype」を入力し [検索]ボタンを2回クリックする ), 。 Apacheが,ファイルをPHPのスクリプトとして解釈するように設定されているので, PHPスクリプトを含むファイルの拡張子は「 .php」か「 .phps」にする。 ##
## httpd.conf -- Apache HTTP server configuration file
~ ~ ~
#ServerAdmin root@localhost
ServerAdmin wwwadmin@epc**.cen.hic.ac.jp
~ ~ ~ nobody User nobody Group ~ ~ ServerName epc**.cen.hic.ac.jp ~ ~ ~ # "/home/wwwadmin/www" DocumentRoot ~ ~ ~ <IfModuule mod_userdir.c> # UserDir public_html UserDir www </IfModuule> ~ ~ ~ <IfModuule mod_dir.c> index.php DirectoryIndex index.html・・・ </IfModuule> ~ ~ ~ <Directory "/home/wwwadmin/www"> ~ ~ ~ # # AddType application/x-tar .tgz AddType application/x-httpd-php .php AddType application/x-httpd-php-source .phps ⑤ 「httpd.conf」ファイルの保存 ・ 保存]ボタンをクリックする。[ サーバ管理者のメールアドレスを設定 n 。(「 」 ) する serveradmin で検索3回目 ユーザ,グループを設定する。 o ( user apache」で検索1回目)「 Webサーバのホスト名を設定する。 p ( servername」で検索3回目)「 DocumentRootを設定する。 q ( documentroot」で検索2回目)「 UserDirを確認する。 r ( userdir」で検索7回目)「 DirectoryIndexを設定する。 s (「directoryIndex で検索2回目」 ) directoryを設定する。 t ( directory」で検索10回目)「 PHPファイルの認識を設定する。 u ( addtype」で検索2回目)「
(3) Apacheの再起動と動作確認 図7 サービスの再起動 ① サービス(Apache)の再起動 (postgreSQLも再起動しておく )。 [ ] [ ], ・ アプリケーション より サーバ設定 [サービス]を選択する。 ・図7の httpd にチェックを入れ「 」 ,[停 止]をクリックし [再起動]をクリ, ックする。 ② 「index.php」の作成 ・geditの[ファイル]より[新規]を選択する。 ・次のように入力する。 <html> <? echo phpinfo(); ?> </html> ・geditの[ファイル]より[保存]を選択する。 ・ファイル名「index.php」を入力する。 ・ 他のフォルダの参照]を選択し 「ファイルシステム ,フォルダ(フォルダ名「/home/[ , 」 wwwadmin/www )を順にダブルクリックし [保存]ボタンをクリックする。」 , ③ ブラウザからの動作確認 図8 http://epc**.cen.hic.ac.jp/index.php ・ブラウザ(Mozilla Firefox)を表示さ せる。 (ブラウザが起動していない場合は, ランチャの[Webブラウザ]をクリック する )。 ・URL「http://epc**.cen.hic.ac.jp/ index.php」を入力し, Enter キーを 押す (図8)。 (4) データベースの使用権限の設定 データベース「testdb」は,作成者「wwwadmin」だけが使用権限を持つ。一方,apacheの 実行者は,Webサーバに対するセキュリティ上の理由でnobodyに限定されている。 SQLコマンド「grant」を使用して,利用者「nobody」がデータベース「testdb」のテーブ
ル「table1」を利用できるように権限を設定する。なお,権限は「select」,「insert」, 「update」,「delete」の各項目ごとに設定が可能であるが,ここでは便宜上 「all」に設定, しnobodyに対してすべての権限を付与する。 ① 利用者の設定 ・次のように入力し,それぞれ Enter キーを押す。 su wwwadmin [root@epc** root]# psql testdb [wwwadmin@epc** root]$
grant all on table1 to nobody; testdb=>
GRAMT z testdb=> \
Access privileges for database "testdb" Schema | Table | Access privileges
---+---+---public | table1 | {wwwadmin=a*r*w*d*R*x*t*/wwwadmin,nobody=arwdRxt/wwwadmin} (1 row) q testdb=> \ ② パーミションの変更 ・デスクトップの[コンピュータ]をダブルクリックする。 ・ ファイルシステム]をダブルクリックする。[ 図9 パーミションの変更 ・フォルダ「home」,「wwwadmin」,「www」を順にダブ ルクリックする。 ・ファイル「index.php」を右クリックし [プロパ, ティ]を選択する。 ・図9のように[アクセス権]タブを選択する。 ・ 所有者「 」,「グループ」,「その他」の図9のよう にチェックを入れる (パーミッション「755 )。 」 ・ファイルの所有者,ファイルのグループをそれぞれ 「wwwadmin」に設定する。また,上位のフォルダも 同様にパーミッションを「755」に変更する。 (5) PHPスクリプトの作成とクライアントからの確認 テーブル「table1」のデータをすべて表示するPHPスクリプトを作成する。 ① ファイル「ichiran.php」の作成 ・geditの[ファイル]より[新規]を選択する。 ・ 端末]に次のように入力し,それぞれ Enter[ キーを押す。 <html> <head> <title>会員データ一覧を表示する</title>
</head> <body> <h3>会員データ一覧を表示する</h3> <? ←① $conn=pg_connect("","","","","testdb"); ←② if (!$conn) { ←③ echo "接続エラーが発生しました n";\ exit; } // データを取り出す
$result = pg_exec($conn,"select id,nam,pre,ag from table1"); ←④ if (!$result) {
echo "エラーが発生しました\n"; exit;
}
// 取り出したデータを表示
echo "<table border=\"20\">"; ←⑤ echo "<tr>"; ←⑥ echo "<td>会員番号</td>"; ←⑦ echo "<td>氏名</td>"; echo "<td>住所</td>"; echo "<td>年令</td>"; ←⑦’ echo "</tr>"; ←⑥’
for ($i = 0; $i < pg_numrows($result); $i++) { ←⑧ $row = pg_fetch_array($result, $i, PGSQL_ASSOC); ←⑨ echo "<tr>";
echo "<td>"; echo pg_result($result,$i,"id"); echo "</td>"; ←⑩
echo "<td>"; echo pg_result($result,$i,"nam"); echo "</td>"; echo "<td>"; echo pg_result($result,$i,"pre"); echo "</td>"; echo "<td>"; echo pg_result($result,$i,"ag"); echo "</td>"; echo "</tr>"; } echo "</table>"; // 接続解除 pg_close($conn); ←⑪ ?> ←①’ </body> </html> 各PHPスクリプトの意味は,次のとおりである。 ①及び①’ スクリプトの開始と終了を示す。Apacheは“<?”と“?>”の間をPHPスクリ プトとして解釈する。 ② データベースtestdbに接続して,コネクションIDを変数$connに返す。 ③ データベースと正しく接続できたかどうかをチェックする。 ④ 接続したデータベースに対してSQLコマンドを実行して,結果を配列変数$resultに
格納する。 ⑤ 表示するテーブルの表を作成する。線の太さは,20。 ⑥及び⑥’ <tr>で挟んだ項目名を表示する。 ⑦ 教示する項目は,<td>で囲む。 ⑧ $i=0 から,データベースの行数まで繰り返す。$i=pg_numrows($result)で行数を取 得する。 ⑨ $i行目を配列として$rowに取得する。 ⑩ $i行目のidを表示する。 ⑪ データベースとの接続を切断する。 ・geditの[ファイル]より[保存]を選択する。 ・ファイル名「index.php」を入力する。 ・ 他のフォルダの参照]を選択し 「ファイルシステム ,フォルダ(フォルダ名「/home/[ , 」 wwwadmin/www )を順にダブルクリックし [保存]ボタンをクリックする。」 , ・ブラウザを起動し,URL「http://epc**.cen.hic.ac.jp/ichiran.php」を入力し, Enter キーを押す (図10)。 図10 ② ファイル「5kenzutu.php」の作成 「 」 。 テーブル table1 のデータから1ぺージに5件のデータ表示PHPスクリプトを作成する ・geditの[ファイル]より[新規]を選択する。 ・ 端末]に次のように入力し,それぞれ Enter[ キーを押す。 <html> <head> <title>会員を5件ずつ表示する</title> </head> <body> <h3>会員を5件ずつ表示する</h3> <?php // 接続設定 $conn=pg_connect("","","","","testdb"); ←① if (!$conn) { echo "接続エラーが発生しました\n";
exit; }
// データ数を取得
$sql = "SELECT COUNT(*) AS cnt FROM table1;"; ←② $res = pg_query($conn, $sql) or die("データ抽出エラー"); ←③ $row = pg_fetch_array($res, 0, PGSQL_ASSOC); ←④ $dtcnt = $row["cnt"]; ←⑤ // 取り出す最大レコード数 $lim = 5; ←⑥ // 表示するページ位置を取得 $p = intval(@$_GET["p"]); ←⑦ if ($p < 1) { ←⑧ $p = 1; } // 表示するデータの位置を取得 $st = ($p - 1) * $lim; ←⑨ // 前のページ/次のページのページ番号を取得 $prev = $p - 1; ←⑩ if ($prev < 1) { $prev = 1; } $next = $p + 1; ←⑪ // データを取り出す
$sql = "SELECT id, nam, pre, ag FROM table1 ORDER BY id ←⑫ LIMIT $lim OFFSET $st;"; ←⑬ $res = pg_query($conn, $sql) or die("データ抽出エラー");
// 取り出したデータを表示 echo "<table border=\"20\">"; echo "<tr>"; echo "<td>会員番号</td>"; echo "<td>氏名</td>"; echo "<td>住所</td>"; echo "<td>年令</td>"; echo "</tr>";
for ($i = 0; $i < pg_numrows($res); $i++) { $row = pg_fetch_array($res, $i, PGSQL_ASSOC); echo "<tr>";
echo "<td>"; echo pg_result($res,$i,"id"); echo "</td>"; echo "<td>"; echo pg_result($res,$i,"nam"); echo "</td>";
echo "<td>"; echo pg_result($res,$i,"pre"); echo "</td>"; echo "<td>"; echo pg_result($res,$i,"ag"); echo "</td>";
echo "</tr>"; }
// 前のページ/次のページへリンク
if ($p > 1) { ←⑭
echo " <a href=\""."?p=$prev\"> ←⑮ 前のページ</a>";
}
if (($next - 1) * $lim < $dtcnt) { ←⑯ echo " <a href=\""."?p=$next\"> ←⑰ 次のページ</a>"; } // 接続を解除 pg_close($conn); ?> </body> </html> 各PHPスクリプトの意味は,次のとおりである。 ① データベースとの接続 ② SELECT文を$SQLに格納する。 ③ pg_queryを実行し,table1のデータを抽出し,$res に格納する。 ④ データの1行目を配列で抽出し,$row に格納する。 ⑤ データのレコード数をカウントし,$dtcnt に格納する。 ⑥ ブラウザに表示する最大レコード数設定する。 ⑦ @$_GET["p"]で現在のページ番号を取得し,intvalで整数化する。 ⑧ 1未満の時は$pを1とする。 ⑨ 次のページを表示するとき,前のページをカウントしないように,開始位置を決め る。 ⑩ 前のページに戻るときの変数を決める。 ⑪ 次のページに進むときの変数を決める。 ⑫ id,nam,pre,ag をidの順番に並べて取得するSELECT文。 ⑬ 最大5人で開始位置を$st とする。 ⑭ もし,$pが1より大きかったときには{ }を実行する。 「 」 , , 。 ⑮ 前のページ をクリックした時 前ページにリンクし URLにページ数を追加する ⑯ もし,レコード数が最後まで表示されてなかったときは 「 」 , , 。 ⑰ 次のページ をクリックした時 次ページにリンクし URLにページ数を追加する ・geditの[ファイル]より[保存]を選択する。 ・ファイル名「5kenzutu.php」を入力する。 ・ 他のフォルダの参照]を選択し 「ファイルシステム ,フォルダ(フォルダ名「/home/[ , 」 wwwadmin/www )を順にダブルクリックし [保存]ボタンをクリックする。」 , ・ブラウザにURL「http://epc**.cen.hic.ac.jp/5kenzutu.php」を入力し, Enter キーを 押す。
図11 ③ ファイル「tuika.php」の作成 テーブル「table1」にデータを追加するPHPスクリプトを作成する。 ・geditの[ファイル]より[新規]を選択する。 ・ 端末]に次のように入力し,それぞれ Enter[ キーを押す。 <html> <head> <title>新規データを追加する</title> </head> <body> <h3>新規データを追加する</h3> <?php // データベースに接続 $conn=pg_connect("","","","","testdb"); if (!$conn) { echo "接続エラーが発生しました\n"; exit; } // 追加するデータを取得 if (count($_POST) > 0) { ←① $id = $_POST["id"]; ←② $nam = $_POST["nam"]; $pre = $_POST["pre"]; $ag = $_POST["ag"]; // データが送信されたときはデータを追加
if (strlen($id) and strlen($nam) and strlen($pre) and strlen($ag)) { ←③ // データ追加
$sql="insert into table1 (id,nam,pre,ag) values ('".$id."','".$nam."','".$pre."
pg_query($conn, $sql) or die("データ追加エラー"); ←⑤ }
}
// データを取り出す
$sql = "SELECT id, nam, pre, ag FROM table1 ORDER BY id"; ←⑥ $res = pg_query($conn, $sql) or die("データ抽出エラー"); ←⑦
// 取り出したデータを表示 echo "<table border=\"20\">"; echo "<tr>"; echo "<td>会員番号</td>"; echo "<td>氏名</td>"; echo "<td>住所</td>"; echo "<td>年令</td>"; echo "</tr>";
for ($i = 0; $i < pg_numrows($res); $i++) { $row = pg_fetch_array($res, $i, PGSQL_ASSOC); echo "<tr>";
echo "<td>"; echo pg_result($res,$i,"id"); echo "</td>";
echo "<td>"; echo pg_result($res,$i,"nam"); echo "</td>";
echo "<td>"; echo pg_result($res,$i,"pre"); echo "</td>"; echo "<td>"; echo pg_result($res,$i,"ag"); echo "</td>";
echo "</tr>"; }
echo "<form method=\"POST\" action=\"".$_SERVER["PHP_SELF"]."\">"; ←⑧ echo "<tr>";
echo "<td><input type=\"text\" name=\"id\"></td>"; ←⑨ echo "<td><input type=\"text\" name=\"nam\"></td>"; ←⑩ echo "<td><input type=\"text\" name=\"pre\"></td>";
echo "<td><input type=\"text\" name=\"ag\"></td>";
echo "<td><input type=\"submit\" value=\"追加\" name=\"sub1\"></td>"; ←⑪ echo "</tr>"; echo "</form>"; echo "</table>"; // 接続を解除 pg_close($conn); ?> </body> </html> 各PHPスクリプトの意味は,次のとおりである。 ① ブラウザに表示されている文字を取得する方法には,POST がある。取得した文 字をカウントし,0より大きければ②へ進む。 ② ブラウザのフォームに入力したid をPOSTにより取得し,$idへ格納する。 ③ $id $nam $pre $ag の文字数を調べて,確認されれば④へ進む。
⑤ 実行
⑥ SELECT で table1 をid 順に並べる。 ⑦ 実行
⑧ 追加項目に文字を表示するためには,form methodで入力文字を取得し,actionで同 じ位置に表示させる。
⑨ id のinput type はtextタイプである。 ⑩ nam のinput type はtextタイプである。
⑪ 追加ボタンを作り,クリックするとsubmitタイプになっているので,内容を送信す る。 ・geditの[ファイル]より[保存]を選択する。 ・ファイル名「tuika.php」を入力する。 ・ 他のフォルダの参照]を選択し 「ファイルシステム ,フォルダ(フォルダ名「/home/[ , 」 wwwadmin/www )を順にダブルクリックし [保存]ボタンをクリックする。」 , ・ブラウザにURL「http://epc**.cen.hic.ac.jp/tuika.php」を入力し, Enter キーを押 す。 図12 (6) クライアント(WindowsXP)からの確認 ・ブラウザ(Internet Explorer)を起動する。 ・URL「http://epc**.cen.hic.ac.jp/ichiran.php」を入力し, Enter キーを押し,確認 する。 ・URL「http://epc**.cen.hic.ac.jp/5kenzutu.php」を入力し, Enter キーを押し,確認 する。 ・URL「http://epc**.cen.hic.ac.jp/tuika.php」を入力し, Enter キーを押し,確認す る。 【演習】 PHPスクリプトを使い,データベース「testdb」のテーブル「table1」を取り込み,1 ぺージに3件のデータ表示させるWebサーバを構築し,クライアント(WindowsXP)のブラウ ザからURL「epc**.cen.hic.ac.jp/3kenzutu.php」を入力し,確認する。