PHPでフォームの二重送信を防止する方法を現役エンジニアが解説【初心者向け】

初心者向けにPHPでフォームの二重送信を防止する方法について現役エンジニアが解説しています。フォームの二重送信とは、複数回リクエストを送ってしまう操作のことです。フォームで二重送信を防止する方法として、PHPのセッションを使う方法を解説します。

TechAcademyマガジンは受講者数No.1のオンラインプログラミングスクールTechAcademy [テックアカデミー]が運営。初心者向けに解説した記事を公開中。現役エンジニアの方はこちらをご覧ください。

PHPでフォームの二重送信を防止する方法について、TechAcademyのメンター(現役エンジニア)が実際のコードを使用して初心者向けに解説します。

そもそもPHPについてよく分からないという方は、PHPとは何なのか解説した記事を読むとさらに理解が深まります。

 

なお本記事は、TechAcademyのオンラインブートキャンプPHP/Laravel講座の内容をもとに紹介しています。

 

田島悠介

今回は、PHPに関する内容だね!

大石ゆかり

どういう内容でしょうか?

田島悠介

PHPでフォームの二重送信を防止する方法について詳しく説明していくね!

大石ゆかり

お願いします!

 
この記事は、PHPプログラムでフォームの二重送信を防止する方法について解説した記事です。

PHPプログラム内で、Web技術の1つ「セッション」を使用する防止方法について解説します。「セッション」についてあまり理解てきていないという方は、「セッション」についての理解しておくと、この記事で解説している内容について理解しやすいと思います。
 

目次

 

二重送信の概要と原因

二重送信とは、例えば個人情報を登録するWebページで個人情報登録フォームを入力し終えた後に「登録」ボタンを押したとします。その後、内部的には、画面からサーバに対して登録をするための「リクエスト」が送信され、サーバ内のプログラムによって、DB(データベース)への登録処理や、登録するデータのファイル出力処理などが行われます。そのような処理が完了した後に画面に対して「レスポンス」が返されます。

そのレスポンスが返却される前に、「登録」ボタンを再度押してしまうと、本来1件しか登録してはいけない個人情報がDBに2件登録されてしまったり、ファイルに2件出力されてしまったりと、システムとしてあってはならないことが起きてしまいます。

これが二重送信と呼ばれる原因の1つの例で、このような二重送信を防止するために画面のプログラムや、サーバのプログラム内に防止対策を施さなければいけません。

この二重送信は、他にも「二重登録」、「二重更新」、「二重リクエスト」と呼ばれることがあります。これらは本質的に同じで、「二重で実行されるシステムとしては行ってはいけない処理」を防止するための処理を実装する必要があります。
 

[PR] PHPプログラミングで挫折しない学習方法を動画で公開中

二重送信を防止する方法

画面側でJavaScriptによる防止対策を実装する方法もありますが、今回はPHPによるサーバサイドプログラム内で、「セッション」を利用して二重送信を防止する方法について解説していきます。

セッションによる二重送信を防止する手順:

  1. 登録(更新)画面でランダムな文字列の「トークン」を発行する
  2. 発行したトークンをセッション変数に格納する
  3. 画面の送信フォーム内「hidden要素」にPOSTするトークンをセットする
  4. 登録(更新)ボタンが押された場合、サーバプログラムで、セットした「セッション変数のトークン」と「POSTされた(hidden要素の)トークン」を比較する
  5. 比較して一致する場合、その後の処理(フォーム登録情報を登録など)を行う

上記手順の処理を行えば、二重送信が行われた際に、「セッション変数のトークン」と「POSTされたトークン」が異なるため、「二重で実行されるシステムとしては行ってはいけない処理」を防止できます。
 

実際に書いてみよう

それでは、実際に上記に記載した二重送信防止の手順を実装したプログラムのサンプルを見て行きましょう。

index.php:

<?php
session_start();

// 二重送信防止用トークンの発行
$token = uniqid('', true);;

//トークンをセッション変数にセット
$_SESSION['token'] = $token;
?>

<!DOCTYPE html>
<html>
<head>
  <meta charset = "utf-8">
  <title>アカウント登録画面</title>
</head>
<body>
<h1>アカウント登録画面</h1>
<form action = "create_account.php" method="POST">
  <div>
    <span>ID:</span>
    <input type="text" name="id">
  </div>
  <br /><br />
  <div>
    <span>PASSWORD:</span>
    <input type="text"name="password">
  </div>
  <input type="hidden" name="token" value="<?php echo $token;?>">
  <button type="submit" value="登録">
</form>
</body>
</html>

create_account.php:

<?php
session_start();

// POSTされたトークンを取得
$token = isset($_POST["token"]) ? $_POST["token"] : "";

// セッション変数のトークンを取得
$session_token = isset($_SESSION["token"]) ? $_SESSION["token"] : "";

// セッション変数のトークンを削除
unset($_SESSION["token"]);

// POSTされたトークンとセッション変数のトークンの比較
if($token != "" && $token == $session_token) {
  // 登録画面送信データの登録を行う
  echo"アカウント登録が完了しました";

} else {
  echo"ERROR:不正な登録処理です";
}
?>

上記のサンプルコードでは、「index.php」の登録画面を開いた際に、二重送信防止用のトークンを発行し、「登録」ボタンを押されたら、「create_account.php」でセッション変数とフォームのhidden要素にセットされたトークンを比較します。同じだった場合、新規アカウント登録処理を行うようなプログラムとなっています。
 

まとめ

以上、PHPプログラムでセッション技術を利用して、フォーム二重送信を防止する方法について解説しました。

二重送信の防止対策は、画面遷移を伴うECサイトを開発する際など必須の技術と言えるので、二重送信の防止対策についてはしっかりマスターしておきましょう。
 

筆者プロフィール

平野大輝(ひらのだいき)

スキル:PHP・Java・JavaScriptを用いて様々なアプリを開発するWebエンジニア。

 

大石ゆかり

内容分かりやすくて良かったです!

田島悠介

ゆかりちゃんも分からないことがあったら質問してね!

大石ゆかり

分かりました。ありがとうございます!

 

TechAcademyでは、初心者でもPHPやフレームワークのLaravelを使ってWebアプリケーション開発を習得できるオンラインブートキャンプPHP/Laravel講座を開催しています。

挫折しない学習方法を知れる説明動画や、現役エンジニアとのビデオ通話とチャットサポート、学習用カリキュラムを体験できる無料体験も実施しているので、ぜひ参加してみてください。