首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 防止頁面後退的 Session 單頁流程控制

     編輯:PHP 相關知識

Web 表單流程 (如註冊、結帳、問卷) 常需防止使用者按「上一頁」回到已完成步驟,造成重複提交或狀態不一致。本文介紹「單一腳本多階段 + Session 狀態機」模式,徹底解決瀏覽器後退問題,無需 JavaScript、跨瀏覽器相容。

核心概念

  • 將步驟 1、2 合併在同一 PHP 檔案 (如 step12.php)。
  • 用 Session 旗標記錄目前階段。
  • 進入階段 2 後,同一 URL 只輸出階段 2 內容,瀏覽器歷史記錄只有一筆,後退鍵會離開整個流程頁,而非回到階段 1。
  • 完成最後階段 (步驟 3) 時清除旗標,允許重新開始。

完整實作

step12.php - 步驟 1 & 2 合併

<?php
session_start();

// 從步驟 1 進入步驟 2
if (isset($_GET['to_step2'])) {
    // 這裡可驗證步驟 1 表單資料
    // if (!valid_step1($_POST)) { header('Location: step12.php?err=1'); exit; }
    $_SESSION['step'] = 2;
    // 可將步驟 1 資料存入 session 供步驟 3 使用
    $_SESSION['step1_data'] = $_POST ?? [];
}

// 狀態機輸出
if (($_SESSION['step'] ?? 1) >= 2) {
    // ----- 步驟 2 內容 -----
    echo '<h1>步驟 2: 確認資料</h1>';
    echo '<p>資料: ' . htmlspecialchars(json_encode($_SESSION['step1_data'])) . '</p>';
    echo '<a href="step3.php">前往步驟 3</a>';
    echo '<p><small>此時按瀏覽器後退鍵,將離開此頁,不會回到步驟 1</small></p>';
} else {
    // ----- 步驟 1 內容 -----
    echo '<h1>步驟 1: 填寫資料</h1>';
    echo '<form method="post" action="?to_step2=1">';
    echo '姓名: <input name="name" required><br>';
    echo 'Email: <input name="email" type="email" required><br>';
    echo '<button type="submit">下一步</button>';
    echo '</form>';
}
?>

step3.php - 完成並重置

<?php
session_start();

// 驗證流程完整性
if (($_SESSION['step'] ?? 0) < 2) {
    header('Location: step12.php');
    exit;
}

// 處理最終提交
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // 整合所有步驟資料
    $allData = array_merge($_SESSION['step1_data'], $_POST);
    // 儲存資料庫、發送郵件等...
    
    // 完成:清除流程狀態
    unset($_SESSION['step'], $_SESSION['step1_data']);
    
    echo '<h1>提交成功!</h1>';
    echo '<a href="step12.php">重新開始</a>';
    exit;
}

// 顯示步驟 3 確認頁
echo '<h1>步驟 3: 最終確認</h1>';
echo '<pre>' . htmlspecialchars(print_r($_SESSION['step1_data'], true)) . '</pre>';
echo '<form method="post">';
echo '<input type="checkbox" name="agree" required> 我同意條款<br>';
echo '<button type="submit">確認送出</button>';
echo '</form>';
?>

進階:通用多步驟流程基類

<?php
abstract class MultiStepFlow {
    protected string $sessionKey;
    protected array $steps = []; // ['step1' => 'Step1Class', ...]
    protected int $currentStep = 1;
    
    public function __construct(string $sessionKey) {
        $this->sessionKey = $sessionKey;
        session_start();
        $this->currentStep = $_SESSION[$this->sessionKey]['step'] ?? 1;
    }
    
    public function handleRequest(): void {
        $action = $_GET['action'] ?? 'view';
        if ($action === 'next' && $this->validateCurrent()) {
            $this->saveStepData();
            $this->currentStep++;
            $_SESSION[$this->sessionKey]['step'] = $this->currentStep;
            header('Location: ' . $this->getUrl());
            exit;
        }
        $this->render();
    }
    
    protected function validateCurrent(): bool { return true; } // 子類覆寫
    protected function saveStepData(): void {
        $_SESSION[$this->sessionKey]['data'][$this->currentStep] = $_POST;
    }
    protected function getAllData(): array {
        return $_SESSION[$this->sessionKey]['data'] ?? [];
    }
    protected function complete(): void {
        unset($_SESSION[$this->sessionKey]);
    }
    abstract protected function render(): void;
    abstract protected function getUrl(): string;
}

// 使用範例
class RegisterFlow extends MultiStepFlow {
    protected array $steps = [1 => 'basic', 2 => 'profile', 3 => 'confirm'];
    
    protected function render() {
        $method = 'renderStep' . $this->currentStep;
        $this->$method();
    }
    protected function renderStep1() { /* 輸出基本資料表單 */ }
    protected function renderStep2() { /* 輸出詳細資料表單 */ }
    protected function renderStep3() { /* 輸出確認頁 */ }
    protected function getUrl() { return '/register.php'; }
}

$flow = new RegisterFlow('register_flow');
$flow->handleRequest();

優缺點分析

優點缺點
✅ 瀏覽器後退鍵完全失效 (歷史只有一筆)❌ 步驟間無法直接用 URL 分享/書籤
✅ 無需 JavaScript、跨裝置相容❌ Session 過期會導致流程中斷
✅ 伺服器端完全控制流程邏輯❌ 多頁簽操作會互相干擾 (共用 Session)
✅ 易於加入驗證、CSRF 保護❌ 不適合極長流程 (建議 < 5 步)

替代方案比較

  • Token + 隱藏欄位:每步驟產生一次性 Token,驗證後失效。支援多頁簽,但實作較複雜。
  • 前端 SPA (Vue/React):單頁應用內部路由控制,體驗最佳,需前端技能。
  • 資料庫暫存 + UUID:每步驟存 DB,URL 帶 UUID,支援分享/續傳,適合長流程。

Session 單頁流程模式是「零前端依賴、快速上線、安全可靠」的經典解法,適合中小型表單精靈、後台管理流程。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved