MySQL, PHP (2)
MySQL, PHP - フォーム処理

出席調査

出席確認として学生証を教室後ろの入り口近くの出席用PCのリーダにタッチせよ. 出席していない回の実験レポートは提出を認めず,0点として計算されるので 注意すること.

講義

前回に引き続いて MySQL を PHP から呼び出す ウェブアプリケーションを作成する.

今回は特に HTML のフォームの処理を PHP を用いて行う内容を扱う.

HTML の form 要素と使って入力欄を作ることができる form 要素の action 属性によって入力されたデータを PHP スクリプトに送ることができる.

入力用のスクリプトとそこから呼び出されるスクリプトを 別のファイルにすることもできるが,1 つのファイルに まとめるために action 属性に自分自身を指定することができる. これを自己参照するページとよぶ.

自己参照するページの場合,そのページが入力段階で呼ばれているのか, 入力が終わって出力段階で呼ばれているのか,ということを スクリプト中で判断することが重要となる. 変数への値の設定が不完全なら入力段階,完全に変数にデータが 入力されていたら出力段階,という方法で判断することが多い.

実習

実習0 前提条件の設定

前回実験と同一である. 各 PC のIPアドレスを再掲する

教卓に向かって左から 1 号機とし, 各班の 1 から 4 号機のIPアドレスは以下の通りとする.サブネットマスクは /16, すなわち 255.255.0.0 とする.

表 13.1 IPアドレス(前回と同じ)

1号機 2号機 3号機 4号機
1 班 172.17.2.1 172.17.2.8 172.17.2.15 172.17.2.22
2 班 172.17.2.29 172.17.2.36 172.17.2.43 172.17.2.50
3 班 172.17.2.2 172.17.2.9 172.17.2.16 172.17.2.23
4 班 172.17.2.30 172.17.2.37 172.17.2.44 172.17.2.51
5 班 172.17.2.3 172.17.2.10 172.17.2.17 172.17.2.24
6 班 172.17.2.31 172.17.2.38 172.17.2.45 172.17.2.52
7 班 172.17.2.4 172.17.2.11 172.17.2.18 172.17.2.25
8 班 172.17.2.32 172.17.2.39 172.17.2.46 172.17.2.53
9 班 172.17.2.5 172.17.2.12 172.17.2.19 172.17.2.26
10 班 172.17.2.33 172.17.2.40 172.17.2.47 172.17.2.54
11 班 172.17.2.6 172.17.2.13 172.17.2.20 172.17.2.27
12 班 172.17.2.34 172.17.2.41 172.17.2.48 172.17.2.55
13 班 172.17.2.7 172.17.2.14 172.17.2.21 172.17.2.28
14 班 172.17.2.35 172.17.2.42 172.17.2.49 172.17.2.56

実習 1 フォーム

実習 1.1 サンプルプログラム

以下の図 13.1 はフォームに入力されたものをそのまま出力するスクリプトである. /var/www/html 直下に form.php というファイル名で作成せよ.(要管理者権限)

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="ja">
  <head>
    <title>Sample of FORM</title>
  </head>

  <body>
    <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="GET">
      Input: <input type="text" name="data" />
      <input type="submit" />
    </form>
<?php
if(isset($_GET['data'])){
  $s = htmlentities($_GET['data']);
  echo '<p>';
  echo "Output: $s";
  echo '</p>';
}
?>
  </body>
</html>

図13.1 form.php

フォームからデータを送るとき,ほとんどの場合は GET メソッドか POST メソッドを使う. GET メソッドは画面表示など情報を引き出すために使い,POST メドッドは ファイルのアップロードなど情報をサーバに送る目的で使う.実際には 検索語句などの単純な情報は GET で送ることが多い.

図 13.1 form.php の form 要素で method ="GET" とあるのは GET メソッドでフォームに入力されたデータを 送るという意味である.GET であればデータは URL エンコードされ,ヘッダの URL 情報として送られる.そのためブラウザのアドレス入力欄に入力したデータが現れる.

form 要素の action="<?php echo $_SERVER['PHP_SELF']; ?>" 属性で,ジャンプ先を自分自身に設定している.

プログラム内部で,最初に呼ばれたとき(入力フェーズ) か,値を入力して送信ボタンを押されたとき(出力フェーズ)かの 判断をしなければならない.form.php では これを isset($_GET['data']) で行っている. isset 関数はデータが設定されていれば真,されていなければ偽を返す 関数なのでこの if 文はデータがセットされているとき(出力フェーズ) のみ実行される.このように,パラメータに値が設定されているかどうかで 入力フェーズか出力フェーズかを判断する手法はよく使われる手法である.

関数は htmlentities はセキュリティ目的のフィルタで, ユーザが入力した文字列からHTMLタグなどの制御能力を持つ 特殊な文字を無害なものに置き換える.

form.php を変更し,整数の入力データの 2 倍の値を出力するスクリプトを作成せよ. 入力は必ず正の整数値であると仮定してよい.

実習 1.2 温度単位変換プログラム

実習1.1 を参考に,単位を摂氏とした温度の整数値を入力とし, 華氏への温度へ変換した値を出力するプログラム c2f.php を作成せよ. 温度の変換公式は摂氏温度を c, 華氏温度をf とすると,

f = 9/5 c + 32

を使え.

このプログラムを最初に呼び出したときの画面は以下のようになる.

c2f input

図13.2 c2f.php 入力フェーズ

上の入力窓に 25 を入力すると摂氏25度に対応する 華氏温度である77が下の図13.3 のように表示されればよい.

c2f output

図13.3 c2f.php 出力フェーズ

アドレスバーにパラメータ data=25 が表示されているのが GET メソッドの特徴である.

実習 1 が完了した学生はTAに学生証番号,氏名, 自分のホストの IP アドレスを連絡せよ. c2f.php の動作確認が済んだ学生は次の実習に進め.

実習 2 フォームを使ったクエリ発行

実習 2.1 insertstudent.php

フォームからユーザの入力した文字列を得られるので それを利用してクエリ文を作って mysqli 関数から データベースに投入すれば良い.以下の図 13.4 は ユーザにフォームを使って studentid, sname フィールドを 入力させて,そのレコードを INSERT するプログラムである. insertstudent.php として設置し,実行せよ.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="ja">
  <head>
    <title>Insert into student</title>
  </head>

  <body>
    <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="POST">
      Student ID: <input type="text" name="si" />
      Student Name: <input type="text" name="sn" />
      <input type="submit" />
    </form>
    <p>
<?php
if(isset($_POST['si']) && isset($_POST['sn'])){
  $sid = htmlentities($_POST['si']);
  $sname = htmlentities($_POST['sn']);
  $mysqli = new mysqli('localhost','expuser','パスワード','exp');
  if ($mysqli->connect_errno){
    echo 'Cannot connet';
    exit();
  }
  $q = "INSERT INTO student (studentid, sname) VALUE ('$sid', '$sname')";
  if($mysqli->query($q)){
    echo "Student ID: $sid, Student Name: $sname, was INSERTed";
  } else {
    echo 'Query failed';
  }
}
?>
    </p>
  </body>
</html>

図13.4 insertstudent.php

insertstudent.php では form.php とは異なり, メソッドとして GET の代わりに POST を使っている.

GET メソッドと POST メソッドでは情報の送り方が異なる. GET では入力された変数名とその値の組を URL 形式にエンコードして ヘッダの URL 情報を使って送信する.このエンコードは スクリプトのファイルの URL の後に ? を追加し"変数名=値" として すべての変数を追加する.例えば 図13.1 form.php のフォームは GET メソッド が指定されているので URL エンコードが行われる.フォームに "25" と入力して 送信ボタンを押すとスクリプトの URL の後に "?data=25" が追加された URL をサーバにリクエストする. ブラウザの URL 入力欄にも表示される.(図13.3 参照)

POST の場合はヘッダの URL ではなくリクエストの本文として書き込む.

GET と POST の表面的な違いは GET の場合すべての送信情報が URL に 含まれることである.このため,ブラウザのアドレス欄で確認できる, 入力データごとブックマークできる,リンクを作成できる,などの特徴がある. POST ではこれらはできない.

機能としては同じように使われる GET と POST だが,設計思想としては 明確なポリシーの違いがあるのでそれを尊重して使い分けるべきである. GET はもともと情報を引き出すためのメソッドで,変数でいえば読み出しにあたる. ただし,ユーザが決めるパラメータの値によって結果を変化させたい場合にその パラメータを GET メソッドで送る.このため検索キーワードなどは GET のパラメータとして送ることが一般的である.変数の書き込みではなく 読み出しに当たるので,同じパラメータであれば何度アクセスしても同じ結果を 返すような使い方のときに GET を使うべきである.

一方,POST は変数で言えば書き込みにあたる.サーバの保持するデータに 変更を加える時に使う.例えばショッピングサイトの注文データや掲示板への 書き込み等はサーバのデータベースに変更を加えるので POST を使うべきである.

まとめると,相手サーバのデータベースに変更を加えない場合は GET, 変更を加える可能性のある場合は POST を使う,という判断基準が適当である.

実習 2.2 insertreport.php

実習 2.1 を参考に,ユーザにフォームを使って studentid, rname フィールドを 入力させて,そのレコードを INSERT するプログラムである,insertreport.php を作成せよ.

実習 3 DELETE

実習 3.1 deletesname.php

前回の実習で扱った内容で,student テーブルから sname フィールドの値は Yamamoto Hiroshi のレコードを削除するためのクエリは ターミナルからの入力では

mysql> DELETE FROM student WHERE sname='Yamamoto Hiroshi';

であった.これを参考に, ユーザにフォームを使って sname フィールドの値を 入力させて,student テーブルから sname フィールドがその値と一致するレコードを消去する プログラムである,deletesname.php を作成せよ. を作成せよ.

実習 3.2 deletername.php

ユーザにフォームを使って rname フィールドの値を 入力させて,report テーブルから rname フィールドが その値と一致するレコードを消去する プログラムである,deletername.php を作成せよ. を作成せよ.

実習 3.3 deletesidrname.php

deletername.php ではレポート名が同じレコードであれば すべて消去されてしまう.WHERE で与える条件に AND などの論理演算の結果を指定することができる. 例えば report テーブルから studentid フィールドが 0BJT0000, rname が MySQL という両方を条件を満たすレコードを 消去する terminal でのクエリ文は

mysql> DELETE FROM report WHERE studentid='0BJT0000' AND rname='MySQL';

である.これを参考に, ユーザにフォームを使って studentid フィールドの値と rname フィールドの値を入力させて, report テーブルから 両方の フィールドの値が 一致するレコードを消去するプログラムである, deletesidrname.php を作成せよ. を作成せよ.

ただし,student, report に登録するデータは以下の条件を満たしている ようにする.

student

report

正しくないデータが大量にある場合は ターミナルから

user1@pc001:~$ mysql -u expuser -D exp -p

でパスワードを入れて exp データベースに接続せよ. -D オプションは使うデータベースを指定するオプションで, "-D exp" で,mysql に入ってから "use exp" を行ったのと 同じ状態で接続できる.この状態で

mysql> DELETE FROM student;
mysql> DELETE FROM report;

などの文でテーブル内のレコードを全て消してから データを入れ直せ.

deletesidname.php については,例えば report テーブルの全データが 以下の場合,

mysql> SELECT * FROM report;
+-----------+--------------+
| studentid | rname        |
+-----------+--------------+
| 0BJT0000  | DNS          |
| 0BJT0000  | MySQL        |
| 0BJT0001  | CGI          |
| 0BJT0002  | firewall     |
| 0BJT0002  | shell script |
| 0BJT0003  | shell script |
| 0BJT0003  | MySQL        |
| 0BJT0001  | MySQL        |
+-----------+--------------+
8 rows in set (0.00 sec)

studentid が 0BJT0003 のデータは 2 件あり, rname が MySQL のデータは 3 件ある. この状態で studentid が 0BJT0003 かつ rname が MySQL である一件分のデータだけ消せなければならない.

十分にテストを行い,実習 3 が完了した学生はTAに学生証番号,氏名, 自分のホストの IP アドレスを連絡せよ.TA が 前回課題の pr05.php とdeletesidrname.php の動作確認を行う. 確認が済んだ学生は実習を終了して良い. (TA は 学生本人のinsertreport.php, pr04.php なども使って AND 条件処理が正しく機能しているか確認)

課題

第 12 回課題「MySQL,PHP フォーム」 を提出せよ.


Updated in December 22, 2014, index.html, Yamamoto Hiroshi