Web制作メモ -トップへ-

[PHP] リロード時の二重送信を防止する

PHP2015.02.03 17:17

ページをリロードした際、ブラウザは最初のアクセスと同じ情報で再度アクセスします。

フォームの送信情報だった場合も、同じデータを再度送るという仕様です。

これの何が都合が悪いかというと、例えばメール送信フォームなどで、メールが何度も送信される原因となるからです。

この現象は二重送信と言われています。

二重投稿を防止する専用の関数はなく、防止するにはそうならないようにプログラムを作成します。

大きく以下の3つの方法が有名です。

上から順に検討すると良いと思います。

リダイレクトを使う方法は、PHPさえ動けばどの環境でも使えます。

セッションを使う方法は、セッションが使えない場合に動きません。

リファラーを使う方法は、ブラウザの実装によって変わる可能性もあり確実性が低いです。

どの方法も「送られたデータを受け取って処理する部分」と「結果を表示する部分」を分けてプログラムを作るのがポイントです。

ここでは、POSTで送られたデータを処理した後リダイレクトする方法を解説します。

データがPOSTで送られたかどうかは$_SERVER['REQUEST_METHOD']で判別できます。

それを使って処理する部分と表示する部分を分けます。

二重送信を防止するコード

if($_SERVER['REQUEST_METHOD'] === 'POST') {
    //この場所でecho $_POST[data];とやっても表示されません
    //データはありますがすぐ下でリダイレクトされるため
    //~ここにデータの処理を書く~
    //処理が終われば自分自身にリダイレクト
    header('Location:http://○○○.○○○/○○○.php', true, 303);
}
else{
    //この場所でecho $_POST[data];とやっても表示されません
    //$_POSTのデータはリダイレクトされ消えています
    //~ここに結果を表示する処理を書く~
}

処理をした後、header()で自分自身にリダイレクトします。

header()の第一引数は、httpから始まるリダイレクト先のURL、第二引数は前回のヘッダーを置換するかどうかで、第三引数はレスポンスコードです。303は「See Other(他を参照せよ)」と言われ、POSTではなくGETでアクセスすると決められています。

リダイレクトされれば、$_SERVER['REQUEST_METHOD']にはGETが入る為、表示する処理のみが実行されます。

リロードされた際も$_SERVER['REQUEST_METHOD']にはGETが入ります。

つまり、$_SERVER['REQUEST_METHOD']にPOSTが入って、処理する部分が実行されるのは最初の一回だけのアクセスとなります。