PHP - Post-Redirect-Get (PRG)
你好,有抱负的程序设计师们!今天,我们将深入探讨一个重要的网页开发模式,称为Post-Redirect-Get,简称PRG。如果你是编程新手,不用担心;我会一步一步地引导你理解这个概念,就像我在教学多年中为无数学生所做的那样。所以,拿起一杯咖啡(或者你最喜欢的饮料),让我们一起开始这段激动人心的旅程!
什么是Post-Redirect-Get (PRG)?
想象一下,你正在填写一个在线订购披萨的表格。你点击提交,然后...哦哦!你不小心刷新了页面。突然,你订了两个披萨而不是一个!这就是Post-Redirect-Get模式试图解决的问题。
PRG是一种网页开发设计模式,当用户在提交表单后刷新页面时,它防止表单的重复提交。它就像你网页应用中的交通警察,确保数据流畅传输,不会意外地重复。
PRG的工作原理
- 用户使用POST请求提交表单。
- 服务器处理表单数据。
- 服务器不是直接发送响应,而是发送一个重定向(通常是到成功页面)。
- 用户的浏览器用GET请求跟随重定向。
- 服务器响应GET请求,返回最终页面。
现在,让我们通过一些代码示例来看看它是如何工作的!
示例1:简单的PRG实现
让我们从一个基本的例子开始,了解PRG在PHP中是如何工作的。我们将创建一个简单的表单,让用户提交他们最喜欢的颜色。
步骤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。
- 如果是,我们将会提交的颜色保存到会话中。
- 然后我们重定向用户到
result.php
。 - 如果有人直接访问这个页面(不是通过POST),我们把他们发送回表单。
步骤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() |
销毁指定的变量 |
记住,年轻的帕德awan,PRG模式就像是网页开发中的原力。它为你的应用带来平衡,防止表单提交的黑暗面。愿代码与你同在!
总之,Post-Redirect-Get模式是你在网页开发工具箱中的强大工具。它通过防止意外的重复提交,帮助创建更健壮、用户友好的应用。随着你在PHP和网页开发的道路上继续前进,你会发现许多情况,PRG可以拯救你的日子。继续练习,保持好奇心,快乐编码!
Credits: Image by storyset