アクセス向上大失敗 www.igros.net
Last updated 2004/8/16
コメントバック 対応

再読込みによる二重投稿防止 -簡単PHP掲示板講座 STEP12-

トップページ > 初心者向け小技の部屋 > 簡単PHP掲示板講座 > 再読込みによる二重投稿防止
[PR]特集 Amazon.co.jp レコメンドコンテンツ



STEP12
・メッセージ投稿後、再読込みによる二重投稿防止対策をする
  [STEP11の問題点] 書込み後、再読込みをすると二重三重書込みになります。
  [要点] httpリクエストを新規に発生させることで逃げます。
参考ソースプログラム
解説
<?php
# プログラム bbs.php STEP12
 $submit = $HTTP_POST_VARS["SUBMIT"];
 if ($submit=="送信") {
  $name = $HTTP_POST_VARS["NAME"];
  $mail = $HTTP_POST_VARS["MAIL"];
  $body = $HTTP_POST_VARS["BODY"];
  if ($name=="" or $body=="") {
   echo '<font color="#FF000">必須項目入力エラー</font><br>';
   echo 'お名前と本文は必ず入力してください<br>';
   echo '<a href="javascript:history.back()">戻る</a>';
   exit;
  }
  # HTML取除き
  $name = htmlspecialchars("$name");
  $mail = htmlspecialchars("$mail");
  $body = htmlspecialchars("$body");
  # メッセージ長1,000文字でカット
  $body = substr($body, 0, 1000);
  $body = str_replace("\r\n", "<br>", $body);
  $dt = date("y/m/d H:i:s");
  $data = file("data.txt");
  $fp = fopen("data.txt", "w");
   fwrite($fp, "$name\t$mail\t$body\t$dt\n");
   $i = 1;
   foreach ($data as $value) {
    if($i < 30) {
     fwrite($fp, "$value");
     $i++;
    }
   }
  fclose($fp);
  header("Location: bbs.php");
  exit;
 }
 # ノーキャッシュヘッダー
 header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
 header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
 header("Cache-Control: no-cache, must-revalidate");
 header("Pragma: no-cache");
 echo '
  <html>
  <head>
  <title>PHP-BBS</title>
  </head>
  <body>
  <h1>PHP-BBS</h1>
  STEP11<br>
  <form method="post" action="bbs.php" accept-charset="x-euc-jp">
  お名前 <input type="text" size="16" maxlength="30" name="NAME">
  メール <input type="text" size="30" maxlength="50" name="MAIL"><br>
  本文<br>
  <textarea rows="10" cols="70" wrap="soft" name="BODY"></textarea><br>
  <input type="submit" name="SUBMIT" value="送信">
  </form>
 ';
 $data = file("data.txt");
 foreach ($data as $value) {
  $view = explode("\t", $value);
   echo '<hr size="5" width="70%" align="left" noshade>';
   if ($view[1]=="") { echo "<font color=\"#000080\"><b>$view[0]</b></font> $view[3]<br>"; }
   else { echo "<a href=\"mailto:$mail\"><font color=\"#000080\"><b>$view[0]</b></font></a> $view[3]<br>"; }
   echo "$view[2]<br>";
 }
 echo '</body></html>';
?>
まず下の図を参考にしてみてください。
PHP Location関数

改善前としたSTEP11までの流れは、この掲示板プログラムが呼び出されると新規書込みか否かを判定し、新規書込みの場合はファイルへ記録、その後状況に関わらず"表示"する流れで処理していました。
この状態で"再読込み"を行うとCGI(PHP)は直前のリクエストを保持しているため、再度同じデータを書込み(重複投稿)表示します。
一方改善では、新規書込みを判定しファイルへ記録してもそのまま表示せず、新規のリクエストを発生させ再度掲示板プログラムを呼び出します。
この時呼び出される状態は[送信]ボタンによる"新規書込み"に該当しないため、"いいえ"の方向へ流れ"表示"に向かいます。
この状態で"再読込み"が繰返されても保持している直前のリクエストは、"表示"する流れで、"記録"の流れにはなりません。

header("Location: bbs.php");のheaderはPHPのHTMLファイル送信に先立って生のHTTPヘッダを送信する命令で、Location: はリダイレクトさせるURLを指定します。
リダイレクトとは強制的に指定したURLへジャンプさせることと思えば良いと思います。
exit;はphpのプログラム強制終了命令で、この命令が実行された時点でプログラムは終了します。

次に表示部分のecho '<html>...、の前にheader命令が4つ並んでいます。
これは、これからブラウザに送る表示内容をブラウザ自身がキャッシュ(記憶)しないでネ!、と言う意味のヘッダーを送っている部分です。
特別あっても無くても良いと思いますが、とりあえず書いています。
各header文の詳しい説明は難しいのでブラウザにキャッシュさせたくない場合のオマジナイと思ってください。

注意!
header命令はecho文などでブラウザへ文字を送信する前に発行しないと意味を成しません。
必ず最初に実行するよう行位置に注意が必要です。

ここまでのサンプル check!

簡単PHP掲示板講座は次のSTEPで最後になります。
ですが、文字色を変えたり、アイコンを出したり、画像添付などのオプション講座も考えています。


<<<< トップ <<< テーマトップ << サブテーマトップ < 前頁次頁 >

www.igros.net
[PR]特集 Amazon.co.jp レコメンドコンテンツ



Copyright(C) アクセス向上大失敗 All Rights Reservd.
version2.0