簡単にいうとPOSTで遷移した先のページで更新ボタンを押すともう一度POSTしますか?って聞かれる問題を解消できる実装パターンとして、PRGパターンというものがあります。
PRGパターンについては以下を参照してください。
- Teeda ExtensionのWikiのPRGパターンについて
- こちらのP13,14あたりご覧ください。
私自身もPRGパターンのコードを学ぶため、PHP4でどのようになるか実装してみました。
問題を確認してみる
まず、簡単な入力画面から表示画面に遷移するアプリを作ってみたいと思います。
とりあえず、何も考えず通常の実装をおこなってみます。
userInput.php
<HTML> <HEAD> </HEAD> <BODY> <FORM action="userView.php" method="post"> <input type="text" name="userName" /> <input type="password" name="password" /> <input type="submit" value="Regist" /> </FORM> </BODY> </HTML>
PRGパターンにしてみる
userInput.php
<?php session_start(); // セッション変数の破棄 unset($_SESSION["userName"]); unset($_SESSION["password"]); // POSTされたら if ( $_SERVER["REQUEST_METHOD"] == "POST" ){ // セッションに書き込みます $_SESSION["userName"] = $_POST["userName"]; $_SESSION["password"] = $_POST["password"]; // REDIRECTします header("Location: userView.php?redirect=true"); exit; } ?> <HTML> <HEAD> </HEAD> <BODY> <FORM action="userInput.php" method="post"> <input type="text" name="userName" /> <input type="password" name="password" /> <input type="submit" value="Regist" /> </FORM> </BODY>
<?php session_start(); if ( $_GET["redirect"] == "true" ){ // リダイレクト時だけ処理したい場合 } $userName = $_SESSION["userName"]; $password = $_SESSION["password"]; ?> <HTML> <HEAD> <meta http-equiv="content-type" content="application/xhtml+xml; charset=EUC-JP" /> </HEAD> <BODY> username = <?php echo $userName; ?><br/> password = <?php echo $password; ?><br/> </BODY> </HTML>
今度は、更新ボタンを押されても問題なく再表示されるはずです。
リダイレクトしているのにGETパラメータが指定されていない!?
GETパラメータ付でリダイレクトさせるとURLが変になるので、値はセッション経由で遷移先に渡すようです。
なので、リダイレクトした先でセッションをサクッと消してしまうと、更新ボタンが押されたときに値がないので表示できなくなります。しばらくはセッションに置いておくしかないと思います。画面数が多いアプリではセッションが膨れ上がらないように適当なタイミングで消去が必要になります。たとえば、TOPページに戻ったら削除とか、ユーザ管理から請求管理にジャンプしたら消すとか。ユースケースの切換え時に消すという感じです。
Teedaではこのようなことによく配慮して実装されていますね。ほんとによくできています。
http://d.hatena.ne.jp/higayasuo/comment?date=20070116#c