連載
» 2000年11月09日 00時00分 公開

PHP4で作るWeb-DBシステム(4):実践編:データベースアプリケーションの作成 前編 (2/3)

[一志達也,株式会社東洋情報システム]

アプリケーションの開発方法

 その手段について早速紹介していきたいところですが、ここは焦らずに順を追うことにしましょう。

 Webアプリケーションを作成する際に、まず行わなくてはならないのが画面のデザインです。つまり、HTMLを使って静的なWebページを作成するのです。この作業を行ったかどうかが後々まで影響を及ぼしますので、手を抜かずにしっかりとデザインを固めておきたいものです。

 今回は、データベースからデータを検索し、更新・削除を行うアプリケーションを作成します。筆者が作成したHTMLと、それをブラウザに表示した画面は、別途図とリストで確認してください(今回は一例を紹介します)。このHTMLのなかで、赤字になっている行は内容が動的に変化する部分です。

 このようにして、HTMLのどの部分が動的に変化するのかを把握しておくことも大切です。画面がシンプルなうちは簡単ですが、画面が複雑になるとこうした作業の重要性も増していきます。今回の例のように限られた画面数であればなくてもなんとかなりますが、大規模なアプリケーションであれば画面遷移図なども作っておきたいところです。

 少し話がそれてしまいましたが、これからHTMLの動的に変化する部分をPHPに書き換えていきます。

両データベース共通の事柄

■HTMLフォーム

 データベースと連携する場合に限らず、動的なページの作成にHTMLフォームを欠かすことはできません。

 HTMLフォームとは、<FORM>〜</FORM>のタグで作成する入力画面のことです。HTMLフォームを使えば、入力されたデータをプログラムに引き渡すことが可能になり、そのデータに基づいた処理が行えるようになります。静的なHTMLを動的なプログラムに書き換える際には、このHTMLフォームの加工も忘れないようにしましょう。

 HTMLフォームの加工には、大きく分けて2つの重要なポイントがあります。1つは各入力項目のNAMEアトリビュートについて。もう1つはフォームによって起動されるプログラムの設定、すなわちFORMタグのACTIONアトリビュートについてです。

 HTMLフォームに入力されたデータは、サブミットボタン(INPUTタグでTYPEがSUBMITに設定されたボタン)を押すことで、指定されたプログラムに引き渡されます。そして、その引き渡すプログラムの設定は、FORMタグのACTIONアトリビュートで行われるのです。そのため、FORMタグの加工を間違えてしまうと、正しいプログラムを呼び出せなくなってしまいます。

 そうした間違いをなくすためにも、各画面を生成するプログラムの名称を先に決め、画面遷移図の一部などに記しておくことをお勧めします。そうすることで、HTMLフォームの加工がスムーズになります。通常、こうした作業はシステムの詳細設計の段階で行われることですが、最近では開発期間短縮のために省略されがちです。

 設計段階の省力化は開発期間を短くするようにも思えますが、手順を省略しすぎると後で苦労することになりかねません。また、一度プログラムに書き換えてしまうと、なかなか後戻りできないのもWebシステムの特徴です。静的なHTMLを作成しながら画面遷移図などを作り、それから詳細設計に落とし込むようにしたいものです。

■値の受け渡し

 またもや話がそれてしまいましたが、次に各入力項目のNAMEアトリビュートについて、注意点を解説しておきます。

 PHPの場合、各入力項目に入力された値は、プログラム側の変数に自動的に格納されます。その際、変数の名前は入力項目のNAMEアトリビュートと同じになります。このため、プログラムを作成する前に、入力項目のNAMEアトリビュートに設定する名称を決めておかなくてはなりません。

 とはいえ、1つ1つの入力項目について名称を決めていくのは容易ではありません。画面数が多ければ膨大な時間がかかってしまいますし、柔軟な対応ができなくなります。

 こうした手間を解消するために命名規則を設けて、例外を除いては機械的に名称を決められるようにしておきます。こうしておけば、HTMLフォーム側とプログラム側で名前が一致しない、といったミスを減らすこともできます。

 命名規則の内容はさまざまですが、入力項目が関係するデータベースの列名に“INP_”を付けるなど、分かりやすいルールを決めておけばいいと思います。入力項目の上から順に1、2、3……など、記号的な命名規則にするのはお勧めできません。直感的ではありませんし、なんといっても画面設計の柔軟性がなくなってしまうからです。

 1つの例として、今回作成するアプリケーションの画面遷移図とプログラム名の命名を紹介します。それに合わせてHTMLの加工も行ったので図1とリストを参照してください。

図1 画面遷移図 図1 画面遷移図

テスト用データベースの構築

 次に、今回使用するテスト環境について確認しておきたいと思います。今回は社員情報のメンテナンスアプリケーションを例に、図のような2つの表を使用します。この表は、Oracleに標準で添付されているデモデータと同じものです。

 データの内容は、図2のとおりです。

図2 今回使用するデモデータベース 図2 今回使用するデモデータベース

■Oracleの場合

 Oracleの場合、デモデータは標準で添付されているので特に準備は必要ありません。SQL*PLUSを使って、ユーザー「scott」、パスワード「tiger」でデータベースに接続し、「select * from tab」の結果を見てください。先ほどの表があることを確認できるはずです。

 もし、ユーザーscottや表が存在しない場合は以下の手順に従って作成してください。なお、SQLはDBAユーザー(例えばSYSTEM)で実行してください。

1.ユーザーを作る

Create User scott
identified by tiger
default tablespace 規定とする表領域名
temporary tablespace 一時使用する表領域名;

*表領域名は環境によって異なります。

2.権限を与える
Grant connect, resource to scott;

3.表や索引を作成する
/u01/app/oracle/product/8.1.6/sqlplus/demo/demobld.sql

■PostgreSQLの場合

 PostgreSQLの場合はOracleのようなデモデータベースが存在しないので、今回のテスト環境用に自分でデータを用意しなくてはなりません。以前に用意した環境ではinitdbを実行するところ、すなわちデータベースインスタンス(Oracleの「インスタンス」とは少し違うことに注意)の作成まで行いました。この状態で「postmaster -S -i」を実行すれば、PostgreSQLが使える状態になるので一度確認しておいてください(補足1)。

 PostgreSQLが使える状態であることを確認したら、createdbコマンドを使ってテスト環境用のデータベースを作成します。これは$POSTGRES_HOMEに格納されているPostgreSQLのコマンドですが、通常のコマンドシェルから実行します。

# createdb データベース名

と入力するとデータベースが作成されると同時に、実行したUNIXユーザーと同じユーザーがデータベースに作成されます。

 データベース名は自由に決めることができます。「test」でもいいですし、社員情報という意味で「employee」などでも構いません(例では「employee」という名称を使います)。正常にデータベースが作成されたら、次は「psql」と呼ばれる対話型のSQL実行ツールを呼び出します。Oracleを知る方ならば、SQL*PLUSと同じようなツール、と思っていただけばいいでしょう。

 psqlはcreatedbと同じく、コマンドラインから呼び出して実行します。このとき、複数のデータベースが存在する可能性があるため、データベース名をパラメータとして与えます。データベース名が「employee」であれば、

# psql employee

と入力します。

 ちなみに、「psql -l」と入力すればPostgreSQLに作成されているデータベースの一覧を表示させることも可能です。

 psqlを起動すると、プロンプトが「データベース名=#」に変化するはずです(例:employee=#)。ここで試しに「\?」と入力してみてください。「\」を先頭に持つコマンドの一覧が表示されます。これは、バックスラッシュコマンドといって、psqlの機能の一部です(psqlを抜けるには\qとします)。

 うまく動作しているようであれば、表(テーブル)を作成するSQLを実行します(リスト1)。

create table emp(
 empno    int,
 ename    text,
 job      text,
 mgr      int,
 hiredate timestamp,
 sal      float,
 comm     float,
 deptno   int
);

create table dept(
 deptno   int,
 dname    text,
 loc      text
);

リスト1 サンプルで使う表の作成

 SQLを実行するときには、リスト1の内容をファイルに保存して、

employee=#\i ファイル名

のように入力するとファイルの内容を実行するので便利です。

 表が作成されると「create」と表示されますが、実行後に「\d」を入力すれば表の一覧を確認することができます。また「\d 表の名前」とすれば、その表の定義を確認できるので覚えておくといいでしょう。

 表が作成できたら、リスト2の内容を使って、データを登録します。先ほどと同じ要領で内容をファイルに保存し、\iコマンドを使って実行させましょう。データ登録後は、念のためにselect文を発行してデータの内容を確認しておいてください。

insert into dept values(10,'ACCOUNTING','NEW YORK');
insert into dept values(20,'RESEARCH','DALLAS');
insert into dept values(30,'SALES','CHICAGO');
insert into dept values(40,'OPERATIONS','BOSTON');

リスト2 サンプルで使うデータの追加

補足1 postmasterコマンドは、initdbを実行したユーザーでのみ実行が可能です。以前に用意した環境では、「postgresql」ユーザーを作成していますが、皆さんの環境に合わせて実行してください。また、postmasterが起動しているかどうかはps -auxコマンドで確認してください。以前にも解説しましたが、postmasterコマンドはシステム起動時に自動起動するようにしておくと便利です。


■Oracleを使う上での選択

 ところで、PHPとOracleデータベースを組み合わせる場合はここで1つの選択が必要です。PHPにはOracleデータベースと連携するための関数が2種類用意されているからです。それが「Oracle関数」(表1)と「Oracle8関数」(表2)です。

 Oracle関数とOracle8関数の違いを簡単に説明すると、OCI8を使っているかどうか、すなわちOracle8クライアントライブラリを使っているかどうかということになります。ここでいうクライアントとは、Webサーバ上にインストールされたクライアントプログラム(Net8 ClientやSQL*PLUSなど)を指します。Oracle8以降のクライアントをインストールしているなら、Oracle8関数を使う方がいいでしょう。

 Oracle8関数は、Oracle関数よりも多くの関数が用意されており、機能も豊富です。また、Oracle8関数を使って、Oracle7サーバに接続することも可能です。ただし、PHP4のインストール時(正確にはconfigure実行時)に、OCI8を利用することを宣言していないと使えません。

 以前の解説ではOCI8を使うことを明示していませんでしたが、ここではOracle8関数を使って説明していきたいと思います。OCI8の使用を宣言する場合は、configure実行時のオプションとして、「--with-oci8」を付けるようにします。このオプションを使う場合、「--with-oracle」オプションは不要ですので注意してください。


下記HTMLをブラウザに表示した画面
<HTML>
<HEAD>
<TITLE>社員検索結果表示画面</TITLE>
</HEAD>
<BODY>
<CENTER>
<TABLE><TR>
<TD ALIGN="center" COLSPAN="2"><HR WIDTH="400"></TD>
</TR><TR>
<TD ALIGN="center" COLSPAN="2"><H1>検索結果表示画面</H1></TD>
</TR><TR>
<TD ALIGN="center" COLSPAN="2">検索の結果一致した社員の一覧です。</TD>
</TR><TR>
<TD ALIGN="center" COLSPAN="2">更新・削除する社員を選択してください。</TD>
</TR><TR>
<TD ALIGN="center" COLSPAN="2"><HR WIDTH="400"></TD>
</TR><TR>
<TD COLSPAN="2"><TABLE BORDER WIDTH="350" ALIGN="center"><TR>
<TH></TH><TH></TH><TH>社員番号</TH><TH>氏名</TH><TH>所属部門</TH>
</TR><TR>
<FORM ACTION="" METHOD="post">
<INPUT TYPE="hidden" NAME="" VALUE="7369">
<TD ALIGN="center"><INPUT TYPE="submit" NAME="" VALUE="更新"></TD>
</FORM>
<FORM ACTION="" METHOD="post">
<INPUT TYPE="hidden" NAME="" VALUE="7369">
<TD ALIGN="center"><INPUT TYPE="submit" NAME="" VALUE="削除"></TD>
</FORM>
<TD>7369</TD>
<TD>SCOTT</TD>
<TD>SALES</TD>
</TR><TR>
<FORM ACTION="" METHOD="post">
<INPUT TYPE="hidden" NAME="" VALUE="0000">
<TD ALIGN="center"><INPUT TYPE="submit" NAME="" VALUE="更新"></TD>
</FORM>
<FORM ACTION="" METHOD="post">
<INPUT TYPE="hidden" NAME="" VALUE="0000">
<TD ALIGN="center"><INPUT TYPE="submit" NAME="" VALUE="削除"></TD>
</FORM>
<TD>0000</TD>
<TD>ICHISHI</TD>
<TD>ENGINEER</TD>

</TR></TABLE></TD>
</TR><TR>
<TD ALIGN="center" COLSPAN="2"><HR WIDTH="400"></TD>
</TR><TR>
<TD ALIGN="right" COLSPAN="2">Copyright 2000, Tatsuya Ichishi</TD>
</TR></TABLE>
</CENTER>
</BODY>
</HTML>

今回作成する画面の1つ。本格的なアプリケーションを開発する際は、まずHTMLで画面デザインを行います。次に、動的な部分(赤字部分)をPHPに置き換えていきます。

関数名 役割
Ora_Logon Oracleへの接続を確立する。 $conn = Ora_Logon("Scott@ORCL","tiger");
Ora_Logoff Oracleへの接続を終了する。 Ora_Logoff($conn);
Ora_Open データカーソルを開く。開いた後はOra_Parseでデータを問い合わせる。 $cursor = Ora_Open($conn);
Ora_Bind PHPの変数を、Oracle SQLのバインド変数に割り当てる(バインド)。 Ora_Bind($cursor, "cename", ":wk_ename", 10, 1);
Ora_Parse SQLもしくはPL/SQLブロックを解析させ、指定したカーソルに割り当てる。ただし実行はしない。 Ora_Parse($cursor, $sql);
Ora_Exec Ora_Parseで解析され、カーソルに割り当てられたSQL、またはPL/SQLブロックを実行する。 Ora_Exec($cursor);
Ora_Fetch 指定したカーソルにデータセットから、1行分のデータを取得する。 Ora_Fetch($cursor);
Ora_GetColumn Fetchで取得した行の列データを取得する。 $cename = Ora_GetColumn($cursor, 1);
Ora_Close Ora_Openで開いたデータカーソルを閉じる。 Ora_Close($cursor);
Ora_ColumnName 指定したデータカーソル中の列名を取得する。 $col_name1 = Ora_ColumnName($cursor, 1);
Ora_ColumnType 指定したデータカーソル中の列のデータ型を取得する。 $col_type1 = Ora_ColumnType($cursor, 1);
Ora_Rollback 実行中のトランザクションをロールバックする。 Ora_Rollback($conn);
Ora_Commit 実行中のトランザクションをコミットする。 Ora_Commit($conn);
Ora_CommitOff オートコミット機能をオフにする。オフにしていてもトランザクションは有効。 Ora_CommitOff($conn);
Ora_CommitOn オートコミット機能をオンにする。 Ora_CommitOn($conn);
Ora_Error Oracleでエラーが発生したときに、そのエラーメッセージを取得する。 $err_msg = Ora_Error($cursor);
Ora_ErrorCode Oracleでエラーが発生したときに、そのエラーコードを取得する。 $err_cd = Ora_ErrorCode($conn);
表1 Oracle関数の一覧
関数名 役割
OCILogon Oracleへの接続を確立する。 $conn = OCILogon("scott", "tiger", "ORCL");
OCIPLogon Oracleへの持続的接続を確立する。Oracle8以降のデータベースで有効。 $conn = OCIPLogon("scott", "tiger", "ORCL");
OCINLogon Oracleへの新規接続を確立する。すでにある接続と明確に区別したい場合に有効。 $conn = OCINLogon("scott", "tiger", "ORCL");
OCILogoff Oracleへの接続を終了する。 OCILogoff($conn);
OCINewCursor データカーソルを開く。開いた後は参照カーソルをバインドするために使用する。 OCINewCursor($conn);
OCIBindByName 実行するSQLに含まれるバインド変数にPHP変数を割り付けする。 OCIBindByName($sql, ":empno", &$empno, 4);
OCIDefineByName カーソルで取得する列の値をPHP変数に割り付けする。 OCIDefineByName($sql, "EMPNO", &$empno);
OCINewDescriptor LOB型やBFILE型のデータを取り扱う際に、記憶領域を確保する。 $lob = OCINewDescriptor($conn, OCI_D_LOB);
OCIParse SQLもしくはPL/SQLブロックを解析する。ただし実行はしない。 OCIParse($conn, $sql);
OCIExecute SQLまたは PL/SQLブロックを実行する。Modeパラメータを指定しない場合は、自動的にコミットされる。 OCIExecute($sql, "OCI_DEFAULT");
OCIFetch 指定したカーソルにデータセットから、1行分のデータを取得する。 OCIFetch($sql);
OCIFetchInto 指定した配列にデータセットから、1行分のデータを取得する。 OCIFetchInto($sql, $emp_array);
OCIFetchStatement 指定した配列にデータセットの全行データを取得する。 OCIFetchStatement($sql, $emp_array);
OCIColumnSize 指定したデータカーソル中の列のサイズを取得する。 OCIColumnSize($sql, 1);
OCIColumnName 指定したデータカーソル中の列の名称を取得する。 OCIColumnName($sql, 1);
OCIColumnType 指定したデータカーソル中の列のデータ型を取得する。 OCIColumnType($sql, 1);
OCIResult Fetchで取得した行の列データを取得する。 $nempno = OCIResult($sql, 1);
OCIColumnIsNULL Fetchで取得した行の列データがNULLであるかを確認する。 OCIColumnIsNULL($sql, 1);
OCIRowCount SQL(Selectは除く)実行時に、操作された行数を取得する。 $rows = OCIRowCount($sql);
OCINumCols Select操作により取得された行に含まれる列数を取得する。 $cols = OCINumCols($sql);
OCIFreeStatement 指定したSQLもしくは PL/SQLブロックに関連する全リソースを解放する。 OCIFreeStatement($sql);
OCIFreeCursor 指定したカーソルに関連する全リソースを解放する。 OCIFreeCursor($cursor);
OCICommit 実行中のトランザクションをコミットする。 OCICommit($conn);
OCIRollback 実行中のトランザクションをロールバックする。 OCIRollback($conn);
OCIServerVersion 指定した接続先のバージョン情報を取得する。 OCIServerVersion($conn);
OCIStatementType 指定したSQLまたは PL/SQLブロックの種類(SELECT,DELETEなど)を取得する。 OCIStatementType($sql);
OCIError 直近のエラーに関するメッセージを取得する。 OCIError($sql);
OCIInternalDebug 内部デバック用出力を有効または無効にする。有効の場合に1。 OCIInternalDebug(1);
表2 Oracle8関数の一覧

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

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

メールマガジン登録

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