PHP - Post-Redirect-Get (PRG)

Xin chào các bạn đang học lập trình! Hôm nay, chúng ta sẽ cùng tìm hiểu một mẫu phát triển web quan trọng叫做 Post-Redirect-Get, hoặc简称 PRG. Đừng lo lắng nếu bạn mới bắt đầu học lập trình; tôi sẽ hướng dẫn bạn từng bước qua khái niệm này, giống như tôi đã làm cho hàng trăm sinh viên trong những năm dạy học của mình. Vậy, hãy lấy một tách cà phê (hoặc đồ uống yêu thích của bạn), và cùng bắt đầu hành trình thú vị này nhé!

PHP - Post-Redirect-Get (PRG)

什么是 Post-Redirect-Get (PRG)?

Hãy tưởng tượng bạn đang điền một biểu mẫu để đặt pizza trực tuyến. Bạn nhấp vào gửi, và sau đó... Oops! Bạn vô tình làm mới trang. Đột nhiên, bạn đã đặt hai pizza thay vì một! Đây là loại vấn đề mà mẫu PRG giúp giải quyết.

PRG là một mẫu thiết kế phát triển web giúp ngăn chặn việc gửi lại biểu mẫu khi người dùng làm mới trang sau khi gửi biểu mẫu. Nó giống như một cảnh sát giao thông cho ứng dụng web của bạn, đảm bảo rằng dữ liệu 流畅 và không bị sao chép ngẫu nhiên.

Cách PRG hoạt động

  1. Người dùng gửi biểu mẫu bằng yêu cầu POST.
  2. Máy chủ xử lý dữ liệu biểu mẫu.
  3. Thay vì gửi phản hồi trực tiếp, máy chủ gửi một hướng dẫn chuyển hướng (thường là đến trang thành công).
  4. Trình duyệt của người dùng theo dõi hướng dẫn chuyển hướng bằng yêu cầu GET.
  5. Máy chủ phản hồi yêu cầu GET với trang cuối cùng.

Bây giờ, hãy cùng xem điều này trong hành động với một số ví dụ mã!

Ví dụ 1: Thực hiện PRG đơn giản

Hãy bắt đầu với một ví dụ cơ bản về cách PRG hoạt động trong PHP. Chúng ta sẽ tạo một biểu mẫu đơn giản cho phép người dùng gửi màu sắc yêu thích của họ.

Bước 1: Biểu mẫu HTML (form.php)

<!DOCTYPE html>
<html>
<head>
<title>Biểu mẫu Màu sắc Yêu thích</title>
</head>
<body>
<h1>Màu sắc yêu thích của bạn là gì?</h1>
<form action="process.php" method="post">
<input type="text" name="color" required>
<input type="submit" value="Gửi">
</form>
</body>
</html>

Biểu mẫu này gửi một yêu cầu POST đến process.php khi được gửi.

Bước 2: Xử lý Biểu mẫu (process.php)

<?php
session_start();

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$color = $_POST['color'];

// Lưu màu sắc vào phiên
$_SESSION['favorite_color'] = $color;

// Chuyển hướng đến trang kết quả
header('Location: result.php');
exit;
} else {
// Nếu ai đó cố gắng truy cập trang này trực tiếp, chuyển hướng họ đến biểu mẫu
header('Location: form.php');
exit;
}

Hãy phân tích điều này:

  1. Chúng ta bắt đầu một phiên để lưu trữ dữ liệu giữa các trang.
  2. Chúng ta kiểm tra nếu phương thức yêu cầu là POST.
  3. Nếu có, chúng ta lưu màu sắc đã gửi vào phiên.
  4. Chúng ta sau đó chuyển hướng người dùng đến result.php.
  5. Nếu ai đó cố gắng truy cập trang này trực tiếp (không qua POST), chúng ta chuyển hướng họ trở lại biểu mẫu.

Bước 3: Hiển thị Kết quả (result.php)

<?php
session_start();

if (isset($_SESSION['favorite_color'])) {
$color = $_SESSION['favorite_color'];
// Xóa biến phiên để ngăn không hiển thị dữ liệu cũ khi làm mới
unset($_SESSION['favorite_color']);
} else {
$color = 'Không có màu sắc được gửi';
}
?>

<!DOCTYPE html>
<html>
<head>
<title>Màu sắc Yêu thích của Bạn</title>
</head>
<body>
<h1>Màu sắc Yêu thích của Bạn</h1>
<p>Bạn đã nói màu sắc yêu thích của bạn là: <?php echo htmlspecialchars($color); ?></p>
<a href="form.php">Gửi màu sắc khác</a>
</body>
</html>

Đây là những gì đang xảy ra:

  1. Chúng ta bắt đầu phiên để truy cập dữ liệu đã lưu.
  2. Chúng ta kiểm tra nếu một màu sắc yêu thích đã được lưu trong phiên.
  3. Nếu có, chúng ta hiển thị nó và sau đó xóa biến phiên.
  4. Nếu không, chúng ta hiển thị một thông báo mặc định.

Bây giờ, ngay cả khi người dùng làm mới trang kết quả, họ sẽ không gửi lại dữ liệu biểu mẫu. Đẹp phải không?

Ví dụ 2: PRG với Giao tiếp Cơ sở Dữ liệu

Hãy nâng cao ví dụ của chúng ta một bước nữa và tưởng tượng chúng ta đang quản lý một hệ thống đặt pizza. Chúng ta sẽ sử dụng cơ sở dữ liệu để lưu trữ đơn đặt hàng và triển khai PRG để ngăn chặn đơn đặt hàng bị lặp lại.

Bước 1: Biểu mẫu Đặt hàng (order_form.php)

<!DOCTYPE html>
<html>
<head>
<title>Biểu mẫu Đặt Pizza</title>
</head>
<body>
<h1>Đặt Pizza của bạn</h1>
<form action="process_order.php" method="post">
<label for="pizza_type">Loại Pizza:</label>
<select name="pizza_type" id="pizza_type" required>
<option value="margherita">Margherita</option>
<option value="pepperoni">Pepperoni</option>
<option value="veggie">Veggie</option>
</select>
<br><br>
<label for="size">Kích thước:</label>
<select name="size" id="size" required>
<option value="small">Nhỏ</option>
<option value="medium">Vừa</option>
<option value="large">Lớn</option>
</select>
<br><br>
<input type="submit" value="Đặt hàng">
</form>
</body>
</html>

Bước 2: Xử lý Đơn đặt hàng (process_order.php)

<?php
session_start();

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$pizza_type = $_POST['pizza_type'];
$size = $_POST['size'];

// Trong một ứng dụng thực tế, bạn sẽ muốn làm sạch và xác minh dữ liệu này

// Kết nối đến cơ sở dữ liệu (thường bạn sẽ đặt này trong một tệp riêng biệt)
$db = new PDO('mysql:host=localhost;dbname=pizza_shop', 'username', 'password');

// Chèn đơn đặt hàng
$stmt = $db->prepare("INSERT INTO orders (pizza_type, size) VALUES (?, ?)");
$stmt->execute([$pizza_type, $size]);

// Lấy ID đơn đặt hàng
$order_id = $db->lastInsertId();

// Lưu ID đơn đặt hàng vào phiên
$_SESSION['last_order_id'] = $order_id;

// Chuyển hướng đến trang xác nhận
header('Location: order_confirmation.php');
exit;
} else {
// Nếu ai đó cố gắng truy cập trang này trực tiếp, chuyển hướng họ đến biểu mẫu
header('Location: order_form.php');
exit;
}

Script này:

  1. Xử lý dữ liệu biểu mẫu.
  2. Chèn đơn đặt hàng vào cơ sở dữ liệu.
  3. Lưu ID đơn đặt hàng vào phiên.
  4. Chuyển hướng đến trang xác nhận.

Bước 3: Xác nhận Đơn đặt hàng (order_confirmation.php)

<?php
session_start();

if (isset($_SESSION['last_order_id'])) {
$order_id = $_SESSION['last_order_id'];
// Xóa biến phiên
unset($_SESSION['last_order_id']);

// Trong một ứng dụng thực tế, bạn sẽ muốn lấy chi tiết đơn đặt hàng từ cơ sở dữ liệu ở đây
// Đối với ví dụ này, chúng ta chỉ hiển thị ID đơn đặt hàng
$message = "Đơn đặt hàng của bạn (ID: $order_id) đã được đặt thành công!";
} else {
$message = "Không tìm thấy đơn đặt hàng gần đây. Vui lòng đặt hàng mới.";
}
?>

<!DOCTYPE html>
<html>
<head>
<title>Xác nhận Đơn đặt hàng</title>
</head>
<body>
<h1>Xác nhận Đơn đặt hàng</h1>
<p><?php echo htmlspecialchars($message); ?></p>
<a href="order_form.php">Đặt đơn hàng khác</a>
</body>
</html>

Trang xác nhận này:

  1. Lấy ID đơn đặt hàng từ phiên.
  2. Hiển thị thông báo xác nhận.
  3. Xóa biến phiên để ngăn không hiển thị cùng một đơn đặt hàng khi làm mới.

Tại sao PRG quan trọng

  1. Ngăn chặn Gửi lại Đơn đặt hàng: Nếu người dùng làm mới trang xác nhận, họ sẽ không vô意间 gửi lại đơn đặt hàng.
  2. Cải thiện Trải nghiệm Người dùng: Người dùng thấy một URL sạch trong thanh địa chỉ, không phải là một chuỗi dài dữ liệu biểu mẫu.
  3. Tuân theo Nguyên tắc REST: Yêu cầu GET được sử dụng để lấy dữ liệu, trong khi yêu cầu POST được sử dụng để gửi dữ liệu.

Các Phương pháp PRG Thường gặp

Dưới đây là bảng các phương pháp thường gặp được sử dụng trong mẫu PRG:

Phương pháp Mô tả
$_SERVER['REQUEST_METHOD'] Kiểm tra phương thức yêu cầu HTTP (GET, POST, v.v.)
header('Location: ...') Gửi hướng dẫn chuyển hướng đến trình duyệt
exit Đảm bảo không có mã nào được thực thi sau hướng dẫn chuyển hướng
session_start() Bắt đầu một phiên mới hoặc tiếp tục một phiên đã.exists
$_SESSION Lưu trữ và truy xuất dữ liệu phiên
isset() Kiểm tra nếu một biến được đặt và không phải NULL
unset() 销毁 một biến đã chỉ định

Nhớ nhé, các bạn trẻ, mẫu PRG giống như sử dụng Lực trong phát triển web. Nó mang lại sự cân bằng cho ứng dụng của bạn, ngăn chặn sự lặp lại của các gửi biểu mẫu không mong muốn. Chúc các bạn may mắn và mã hóa vui vẻ!

Credits: Image by storyset