PHP - Post-Redirect-Get (PRG)
こんにちは、未来のプログラマーたち!今日は、Web開発における重要なパターンであるPost-Redirect-Get、略してPRGについて深く掘り下げます。プログラミングが初めての方也不用担心;私はこの概念をステップバイステップでガイドします。これまでに多くの学生を指導してきました。コーヒー(またはお気に入りの飲み物)を手に取り、一緒にこの興奮する旅に出発しましょう!
Post-Redirect-Get (PRG)とは?
オンラインでピザを注文するフォームを想像してみてください。フォームを送信した後、間違ってページをリフレッシュしてしまうと、突然、ピザが2つ注文された!このような問題を解決するのがPRGパターンの役割です。
PRGは、ユーザーがフォームを送信した後ページをリフレッシュしたときの重複フォーム送信を防止するWeb開発のデザインパターンです。Webアプリケーションのための交通警察官のように、データがスムーズに流れ、誤って重複しないようにします。
PRGの仕組み
- ユーザーはPOSTリクエストを使ってフォームを送信します。
- サーバーはフォームデータを処理します。
- 応答を直接送信する代わりに、サーバーはリダイレクト(通常は成功ページに)を送信します。
- ユーザーのブラウザはGETリクエストでリダイレクトを追随します。
- サーバーはGETリクエストに最終ページで応答します。
では、コードの例でこれを見てみましょう!
例1: シンプルなPRG実装
まず、PHPでのPRGの基本例を見てみましょう。ユーザーが好きな色を送信できるシンプルなフォームを作成します。
ステップ1: HTMLフォーム (form.php)
<!DOCTYPE html>
<html>
<head>
<title>好きな色のフォーム</title>
</head>
<body>
<h1>あなたの好きな色は何ですか?</h1>
<form action="process.php" method="post">
<input type="text" name="color" required>
<input type="submit" value="送信">
</form>
</body>
</html>
このフォームは、送信時にprocess.php
にPOSTリクエストを送信します。
ステップ2: フォームの処理 (process.php)
<?php
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$color = $_POST['color'];
// 色をセッションに保存
$_SESSION['favorite_color'] = $color;
// リダイレクト先の結果ページにリダイレクト
header('Location: result.php');
exit;
} else {
// このページに直接アクセスされた場合、フォームにリダイレクト
header('Location: form.php');
exit;
}
これを分解すると:
- セッションを開始します。
- リクエストメソッドがPOSTかどうかを確認します。
- POSTの場合、送信された色をセッションに保存します。
- ユーザーを
result.php
にリダイレクトします。 - 直接このページにアクセスされた場合、フォームにリダイレクトします。
ステップ3: 結果の表示 (result.php)
<?php
session_start();
if (isset($_SESSION['favorite_color'])) {
$color = $_SESSION['favorite_color'];
// セッション変数をクリアしてリフレッシュ時の古いデータを表示防止
unset($_SESSION['favorite_color']);
} else {
$color = '色が送信されていません';
}
?>
<!DOCTYPE html>
<html>
<head>
<title>あなたの好きな色</title>
</head>
<body>
<h1>あなたの好きな色</h1>
<p>あなたが好きな色は:<?php echo htmlspecialchars($color); ?>です。</p>
<a href="form.php">別の色を送信する</a>
</body>
</html>
ここで起こっていることは:
- セッションを再開して保存されたデータにアクセスします。
- 好きな色がセッションに保存されているか確認します。
- 保存されている場合、それを表示し、セッション変数をクリアします。
- 保存されていない場合、デフォルトメッセージを表示します。
これにより、ユーザーが結果ページをリフレッシュしてもフォームデータを再送信しません。素晴らしいですね?
例2: データベースとの連携におけるPRG
例を一歩進めて、ピザ注文システムを運営しているとします。データベースに注文を保存し、PRGを用いて重複注文を防止します。
ステップ1: 注文フォーム (order_form.php)
<!DOCTYPE html>
<html>
<head>
<title>ピザ注文フォーム</title>
</head>
<body>
<h1>ピザを注文する</h1>
<form action="process_order.php" method="post">
<label for="pizza_type">ピザの種類:</label>
<select name="pizza_type" id="pizza_type" required>
<option value="margherita">マルゲリータ</option>
<option value="pepperoni">ペッパロニ</option>
<option value="veggie">ベジ</option>
</select>
<br><br>
<label for="size">サイズ:</label>
<select name="size" id="size" required>
<option value="small">小</option>
<option value="medium">中</option>
<option value="large">大</option>
</select>
<br><br>
<input type="submit" value="注文する">
</form>
</body>
</html>
ステップ2: 注文の処理 (process_order.php)
<?php
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$pizza_type = $_POST['pizza_type'];
$size = $_POST['size'];
// 実際のアプリケーションでは、この入力をサニタイズして検証する必要があります
// データベースに接続(通常は別のファイルにします)
$db = new PDO('mysql:host=localhost;dbname=pizza_shop', 'username', 'password');
// 注文をデータベースに挿入
$stmt = $db->prepare("INSERT INTO orders (pizza_type, size) VALUES (?, ?)");
$stmt->execute([$pizza_type, $size]);
// 注文IDを取得
$order_id = $db->lastInsertId();
// 注文IDをセッションに保存
$_SESSION['last_order_id'] = $order_id;
// 確認ページにリダイレクト
header('Location: order_confirmation.php');
exit;
} else {
// このページに直接アクセスされた場合、フォームにリダイレクト
header('Location: order_form.php');
exit;
}
このスクリプトは:
- フォームデータを処理します。
- データベースに注文を挿入します。
- 注文IDをセッションに保存します。
- 確認ページにリダイレクトします。
ステップ3: 注文確認 (order_confirmation.php)
<?php
session_start();
if (isset($_SESSION['last_order_id'])) {
$order_id = $_SESSION['last_order_id'];
// セッション変数をクリア
unset($_SESSION['last_order_id']);
// 実際のアプリケーションでは、データベースから注文の詳細を取得します
// ここでは、注文IDを表示するだけ
$message = "あなたの注文(ID: $order_id)が無事に受付られました!";
} else {
$message = "最近の注文が見つかりません。新しい注文をしてください。";
}
?>
<!DOCTYPE html>
<html>
<head>
<title>注文確認</title>
</head>
<body>
<h1>注文確認</h1>
<p><?php echo htmlspecialchars($message); ?></p>
<a href="order_form.php">別の注文をする</a>
</body>
</html>
この確認ページは:
- 注文IDをセッションから取得します。
- 確認メッセージを表示します。
- セッション変数をクリアします。
これにより、ユーザーが確認ページをリフレッシュしても、誤って同じ注文を再送信しません。
PRGの重要性
- 重複送信を防止します:ユーザーが確認ページをリフレッシュしても、意図せずに同じ注文を再送信しません。
- ユーザー体験を向上させます:ユーザーはクリーンなURLをアドレスバーに見せることができます。
- REST原則に従います:GETリクエストはデータを取得するために、POSTリクエストはデータを送信するために使用されます。
PRGで使用される一般的なメソッド
以下はPRGパターンで使用される一般的なメソッドの表です:
メソッド | 説明 |
---|---|
$_SERVER['REQUEST_METHOD'] |
HTTPリクエストメソッド(GET、POSTなど)を確認します |
header('Location: ...') |
ブラウザにリダイレクトヘッダーを送信します |
exit |
リダイレクト後、以降のコードを実行しないようにします |
session_start() |
新しいセッションを開始または既存のセッションを再開します |
$_SESSION |
セッションデータを保存および取得します |
isset() |
変数が設定されておりNULLでないか確認します |
unset() |
指定された変数を破壊します |
若いパダワンたち、PRGパターンはWeb開発におけるフォースのように、フォームの重複送信を防止する力を持っています。アプリケーションにバランスをもたらし、ユーザー体験を向上させます。コードに力を注ぎ、幸せなプログラミングを!
Credits: Image by storyset