続いて、今作成した検索画面に条件を入力し、検索できるようにしましょう。入力した条件を受け取って検索するのは、検索結果画面(emp_query.php)の役割です。この画面でも先ほどと同様にデータを取得するのですが、入力された条件を受け取るところでテクニックが必要になります。
画面2 これをemp_query.phpで生成します
まずは、検索条件を無視して社員の一覧を作成できるようにします(Oracle用:リスト5、PostgreSQL用:リスト6)。このように、一度に作ろうとせず、段階的に作成することが重要です。ここまでの手順は先ほどまでと変わりませんから、何も補足する必要はないでしょう。
無事に社員一覧が表示されたら、次は条件を入力できるように少しずつ改良していきます。まずは社員番号を検索条件として使えるようにします。
今回のような条件入力画面で最も気を付けなくてはならないことは、入力条件は必ずしも入力されないことです。従って、検索に使われるselect文も、やはり動的なものでなければなりません。そこで、文字列連結とif文を使って、条件が入力されたときだけselect文に条件を付けるようにします。
これまではselect文を直接関数に渡していましたが、今回は変数に格納してから関数に渡すようにします。そうすることで、変数に格納されたselect文に対して文字列連結が行えるようになります。リスト7とリスト8は完成したプログラムですが、if文の中で文字列連結を使っていることが分かります。
$sql = "select e.empno, e.ename, d.dname
from emp e, dept d where e.deptno = d.deptno";
if (!empty($inp_empno)) {
$sql = $sql. " and e.empno = ". $inp_empno;
} |
このとき、if文の条件は検索条件の入力があるかどうかです。この判定にはempty関数が便利です。empty関数は、変数に値があるかないかを判断し、値がなければTRUEを返します。従って、値があることを確認したければ、それを否定して「!empty」とすればいいのです。
empty関数に似た関数として、isset関数も用意されていますが、こちらは変数が存在するかどうかのチェックを行います。HTMLフォームを使った場合、たとえ値を入力しなくても、入力項目はすべてプログラムに引き渡されます。つまり値を入力しなくても変数は存在するということなので、isset関数では役割を果たせません。
また、コンボボックス(<SELECT>タグ)を使っている部門名称については、条件の判断が異なります。今回のコンボボックスでは、「指定なし」という選択肢を設け、その値として「NULL」が渡されるようになっています。この値が渡された場合は条件として無視しなければなりません。この処理についてはリスト7、リスト8を見ればお分かりだと思いますが、empty関数とANDで組み合わせて条件を指定しています。
if (!empty($inp_dept) and ($inp_dept !=
"NULL")) |
こうして条件を判断してselect文を組み立てることができれば、あとは普通にデータを取得するだけです。データの取得法さえ分かってしまえば、いくらでも応用することが可能です。その応用が難しいのかもしれませんが、PHPでデータベースと連携することが、いかに簡単かお分かりいただけると思います。
これで検索結果を表示する画面は完成ですが、条件に一致する結果がなかった場合のルーチンも作っておくと、より本格的なアプリケーションらしくなります。このルーチンについては紹介しませんから、皆さんなりに考えてみてください。ポイントは、一致する結果がなかった場合は一覧表の枠や列ヘッダを作らないことです。
ここまでの内容を理解していれば、更新画面(emp_update.php)を自力で作るのもそれほど難しくないでしょう。ここから先はご自分で作成してみてください。とはいえ、それだけではあんまりなので、プログラミングする際のポイントを以下に解説しておきます。
emp_update.phpにはinp_empnoという変数に社員番号が渡されますから、これを使って社員のデータを表示してやります。削除画面となるemp_del.phpの方も、同様に社員名を表示するようにしてやれば、残るは操作結果画面(emp_commit.php)を作るだけです。
ところが、前回も掲載した図1を再確認していただくと分かるように、この画面ではすべてのデータ操作を引き受けます。従って、このプログラム1つで追加・更新・削除ができなければならないのです。このとき、どうやって行う操作を判断するかという問題が発生します。
図1 画面変遷図(前回と同じもの)
非常に難しい問題のようですが、この答えは意外に簡単です。実は、こうした問題が発生することを予測し、追加・更新・削除画面のボタンの文字(ラベル)を変えてあるのです。つまり、押したボタンの文字を判別することで、どの操作をすべきか判断できるということです。
ボタンの文字は、それぞれ「登録完了」(追加)・「更新完了」(更新)・「確認」(削除)となっていますから、これを判断します。これが、もし「OK」や「変更」などというありがちな文字で統一されていたら、呼び出し元のプログラム名で判断するなど、ややこしい手段を使うはめになってしまいます。それに比べて、ボタンの文字で判断する方法は簡単で確実ですからお勧めです。
ボタンの文字は、inp_submitという名称の変数に格納され、プログラム側で呼び出せるようになっています。データ操作を行うときに、inp_submit変数の内容をif文で判断し、先ほどの文字列と比較してください。そして、各操作で必要な変数(入力値)を読み取り、SQLを組み立ててやるのです。
あとは、そのSQLを実行するだけです。SQLを実行する方法は、検索ルーチンとまったく同様で、その後にデータを取り出さないところが違うだけです。その代わりに、データ操作ではコミット(確定)かロールバック(取り消し)を行わなければなりません。これだけでデータ操作プログラムは完成しますから、検索画面を作ることができれば難しくないはずです。
コツとしては、あくまでも段階的に作ること。まずは操作を判断するようにし、それからSQLを作るようにして正しいSQLが作られることを確認。それができたらSQLを実行するようにし、コミットを行わせるのです。段階的に作っていけば問題も見つけやすく、確実なプログラムを作成できます。
プログラミングの解説としては、もっと付け加えておきたいこともあるのですが、今回はここまでとさせていただきます。5回にわたりお付き合いいただきありがとうございました。今後も新しいテーマについて解説していきたいと思いますので、またお付き合いいただければ幸いです。
<?php
$conn=ocilogon("scott","tiger","orcl");
?>
<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>
<?php
$sql = "select e.empno, e.ename, d.dname from emp
e, dept d where e.deptno = d.deptno";
$stmt = OCIParse($conn, $sql);
OCIDefineByName($stmt, "EMPNO", &$empno);
OCIDefineByName($stmt, "ENAME", &$ename);
OCIDefineByName($stmt, "DNAME", &$dname);
OCIExecute($stmt);
while (OCIFetch($stmt)) {
print ('<TR>'."\n");
print ('<FORM ACTION="emp_update.php"
METHOD="post">'."\n");
print ('<INPUT TYPE="hidden"
NAME="inp_empno" VALUE="'.$empno.'">'."\n");
print ('<TD ALIGN="center"><INPUT
TYPE="submit" NAME="inp_submit" VALUE="更新"></TD>'."\n");
print ('</FORM>'."\n");
print ('<FORM ACTION="emp_del.php"
METHOD="post">'."\n");
print ('<INPUT TYPE="hidden"
NAME="inp_empno" VALUE="'.$empno.'">'."\n");
print ('<TD ALIGN="center"><INPUT
TYPE="submit" NAME="inp_submit" VALUE="削除"></TD>'."\n");
print ('</FORM>'."\n");
print ('<TD>'.$empno.'</TD>'."\n");
print ('<TD>'.$ename.'</TD>'."\n");
print ('<TD>'.$dname.'</TD>'."\n");
print ('</TR>'."\n");
}
OCIFreeStatement($stmt);
?>
</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>
<?php
OCILogoff($conn);
?>
|
リスト5 条件を意識せずに作った例(Oracle用) |
<?php
$conn=pg_Connect("host=cinderella dbname=employee
port=5432");
?>
<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>
<?php
$sql = "select e.empno, e.ename, d.dname from emp
e, dept d where e.deptno = d.deptno";
$i = 0;
$result = pg_Exec($conn, $sql);
if ($result) {
do {
@$row = pg_Fetch_Row ($result,
$i);
if ($row) {
print ('<TR>'."\n");
print ('<FORM ACTION="emp_update.php"
METHOD="post">'."\n");
print ('<INPUT
TYPE="hidden" NAME="inp_empno" VALUE="'.$row[0].'">'."\n");
print ('<TD ALIGN="center"><INPUT
TYPE="submit" NAME="inp_submit" VALUE="更新"></TD>'."\n");
print ('</FORM>'."\n");
print ('<FORM ACTION="emp_del.php"
METHOD="post">'."\n");
print ('<INPUT
TYPE="hidden" NAME="inp_empno" VALUE="'.$row[0].'">'."\n");
print ('<TD ALIGN="center"><INPUT
TYPE="submit" NAME="inp_submit" VALUE="削除"></TD>'."\n");
print ('</FORM>'."\n");
print ('<TD>'.$row[0].'</TD>'."\n");
print ('<TD>'.$row[1].'</TD>'."\n");
print ('<TD>'.$row[2].'</TD>'."\n");
print ('</TR>'."\n");
$i++;
}
} while ($row);
}
?>
</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>
<?php
pg_Close($conn);
?> |
リスト6 条件を意識せずに作った例(PostgreSQL用) |
<?php
$conn=ocilogon("scott","tiger","orcl");
?>
<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>
<?php
$sql = "select e.empno, e.ename, d.dname from emp
e, dept d where e.deptno = d.deptno";
if (!empty($inp_empno)) {
$sql = $sql. " and e.empno = ".
$inp_empno;
}
if (!empty($inp_ename)) {
$sql = $sql. " and e.ename like '%".
$inp_ename. "%'";
}
if (!empty($inp_dept) and ($inp_dept != "NULL"))
{
$sql = $sql. " and e.deptno = ".
$inp_dept;
}
$stmt = OCIParse($conn, $sql);
OCIDefineByName($stmt, "EMPNO", &$empno);
OCIDefineByName($stmt, "ENAME", &$ename);
OCIDefineByName($stmt, "DNAME", &$dname);
OCIExecute($stmt);
while (OCIFetch($stmt)) {
print ('<TR>'."\n");
print ('<FORM ACTION="emp_update.php"
METHOD="post">'."\n");
print ('<INPUT TYPE="hidden"
NAME="inp_empno" VALUE="'.$empno.'">'."\n");
print ('<TD ALIGN="center"><INPUT
TYPE="submit" NAME="inp_submit" VALUE="更新"></TD>'."\n");
print ('</FORM>'."\n");
print ('<FORM ACTION="emp_del.php"
METHOD="post">'."\n");
print ('<INPUT TYPE="hidden"
NAME="inp_empno" VALUE="'.$empno.'">'."\n");
print ('<TD ALIGN="center"><INPUT
TYPE="submit" NAME="inp_submit" VALUE="削除"></TD>'."\n");
print ('</FORM>'."\n");
print ('<TD>'.$empno.'</TD>'."\n");
print ('<TD>'.$ename.'</TD>'."\n");
print ('<TD>'.$dname.'</TD>'."\n");
print ('</TR>'."\n");
}
OCIFreeStatement($stmt);
?>
</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>
<?php
OCILogoff($conn);
?>
|
リスト7 完成した検索結果画面(Oracle用) |
<?php
$conn=pg_Connect("host=cinderella dbname=employee
port=5432");
?>
<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>
<?php
$sql = "select e.empno, e.ename, d.dname from emp
e, dept d where e.deptno = d.deptno";
if (!empty($inp_empno)) {
$sql = $sql. " and e.empno = ".
$inp_empno;
}
if (!empty($inp_ename)) {
$sql = $sql. " and e.ename like '%".
$inp_ename. "%'";
}
if (!empty($inp_dept) and ($inp_dept != "NULL"))
{
$sql = $sql. " and e.deptno = ".
$inp_dept;
}
$i = 0;
$result = pg_Exec($conn, $sql);
if ($result) {
do {
@$row = pg_Fetch_Row ($result,
$i);
if ($row) {
print ('<TR>'."\n");
print ('<FORM ACTION="emp_update.php"
METHOD="post">'."\n");
print ('<INPUT
TYPE="hidden" NAME="inp_empno" VALUE="'.$row[0].'">'."\n");
print ('<TD ALIGN="center"><INPUT
TYPE="submit" NAME="inp_submit" VALUE="更新"></TD>'."\n");
print ('</FORM>'."\n");
print ('<FORM ACTION="emp_del.php"
METHOD="post">'."\n");
print ('<INPUT
TYPE="hidden" NAME="inp_empno" VALUE="'.$row[0].'">'."\n");
print ('<TD ALIGN="center"><INPUT
TYPE="submit" NAME="inp_submit" VALUE="削除"></TD>'."\n");
print ('</FORM>'."\n");
print ('<TD>'.$row[0].'</TD>'."\n");
print ('<TD>'.$row[1].'</TD>'."\n");
print ('<TD>'.$row[2].'</TD>'."\n");
print ('</TR>'."\n");
$i++;
}
} while ($row);
}
?>
</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>
<?php
pg_Close($conn);
?> |
リスト8 完成した検索結果画面(PostgreSQL用) |