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

PHP 核取方塊批次刪除完整實作:從表單構建到防注入刪除邏輯

     編輯:PHP 綜合知識

核心流程圖解

列表頁 (list.php) → 勾選 ID → 送出 → 處理頁 (delete.php) → 驗證/刪除 → 導回列表

列表頁:動態產生核取方塊表單

<?php
// list.php
$pdo = new PDO('mysql:host=localhost;dbname=school;charset=utf8', 'root', 'password');
$stmt = $pdo->query('SELECT sID, sName, sSex, sPhone FROM student');
$students = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>學生名單</title></head><body>
<form action="delete.php" method="post">
<table border="1" cellpadding="5" cellspacing="0">
  <thead>
    <tr><th>選擇</th><th>學號</th><th>姓名</th><th>性別</th><th>電話</th></tr>
  </thead>
  <tbody>
<?php foreach ($students as $stu): ?>
    <tr>
      <td><input type="checkbox" name="ids[]" value="<?= htmlspecialchars($stu['sID']) ?>"></td>
      <td><?= htmlspecialchars($stu['sID']) ?></td>
      <td><?= htmlspecialchars($stu['sName']) ?></td>
      <td><?= htmlspecialchars($stu['sSex']) ?></td>
      <td><?= htmlspecialchars($stu['sPhone']) ?></td>
    </tr>
<?php endforeach; ?>
  </tbody>
</table>
<p><input type="submit" value="刪除選取" onclick="return confirm('確定刪除選中的學生嗎?')"></p>
</form>
</body></html>

刪除處理頁:預處理語句防注入 + 事務保證原子性

<?php
// delete.php
declare(strict_types=1);

$pdo = new PDO('mysql:host=localhost;dbname=school;charset=utf8', 'root', 'password', [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_EMULATE_PREPARES   => false, // 真實預處理
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);

// 1. 取得並驗證 ID 陣列
$ids = $_POST['ids'] ?? [];
if (!is_array($ids) || empty($ids)) {
    die('未選擇任何記錄');
}

// 2. 過濾:只保留正整數
$ids = array_filter($ids, fn($v) => ctype_digit((string)$v));
if (empty($ids)) {
    die('無效的 ID 參數');
}

// 3. 建立佔位符字串 (?,?,...)
$placeholders = implode(',', array_fill(0, count($ids), '?'));

// 4. 事務執行刪除
try {
    $pdo->beginTransaction();
    $stmt = $pdo->prepare("DELETE FROM student WHERE sID IN ($placeholders)");
    $stmt->execute($ids);
    $deleted = $stmt->rowCount();
    $pdo->commit();

    echo "<p>成功刪除 $deleted 筆記錄</p>";
} catch (PDOException $e) {
    $pdo->rollBack();
    error_log('刪除失敗: ' . $e->getMessage());
    echo "<p style='color:red'>刪除過程發生錯誤,已回滾</p>";
}

echo '<p><a href="list.php">返回列表</a></p>';

進階強化:軟刪除 + 審計日誌

// 資料表新增欄位
ALTER TABLE student ADD COLUMN deleted_at DATETIME NULL DEFAULT NULL;
ALTER TABLE student ADD INDEX idx_deleted (deleted_at);

// 刪除邏輯改為 UPDATE
$stmt = $pdo->prepare("UPDATE student SET deleted_at = NOW() WHERE sID IN ($placeholders)");

// 同步寫入審計表
$auditStmt = $pdo->prepare('INSERT INTO audit_log (action, table_name, record_ids, operator, created_at) VALUES (?,?,?,?,NOW())');
$auditStmt->execute(['soft_delete', 'student', json_encode($ids), $_SESSION['admin_id'] ?? 'unknown']);

// 查詢時自動排除軟刪除
$stmt = $pdo->query('SELECT * FROM student WHERE deleted_at IS NULL');

前端增強:全選/反選 + AJAX 無刷新刪除

<!-- list.php 表單上方加入 -->
<button type="button" id="selectAll">全選</button>
<button type="button" id="invertSelect">反選</button>

<script>
document.getElementById('selectAll').onclick = () =>
  document.querySelectorAll('input[name="ids[]"]').forEach(cb => cb.checked = true);
document.getElementById('invertSelect').onclick = () =>
  document.querySelectorAll('input[name="ids[]"]').forEach(cb => cb.checked = !cb.checked);

// AJAX 刪除(可選)
document.querySelector('form').onsubmit = async (e) => {
  e.preventDefault();
  const ids = Array.from(document.querySelectorAll('input[name="ids[]"]:checked')).map(cb => cb.value);
  if (!ids.length) return alert('請先勾選');
  if (!confirm(`確定刪除 ${ids.length} 筆記錄?`)) return;

  const res = await fetch('delete_ajax.php', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({ids})
  });
  const data = await res.json();
  alert(data.msg);
  if (data.success) location.reload();
};
</script>

delete_ajax.php(API 端點)

<?php
header('Content-Type: application/json');
$input = json_decode(file_get_contents('php://input'), true);
$ids = array_filter($input['ids'] ?? [], 'ctype_digit');

if (empty($ids)) {
    echo json_encode(['success' => false, 'msg' => '無效 ID']);
    exit;
}

$pdo = new PDO('mysql:host=localhost;dbname=school;charset=utf8', 'root', 'password', [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
$placeholders = implode(',', array_fill(0, count($ids), '?'));
$stmt = $pdo->prepare("DELETE FROM student WHERE sID IN ($placeholders)");
$stmt->execute($ids);

echo json_encode(['success' => true, 'msg' => "刪除 {$stmt->rowCount()} 筆"]);

安全檢查清單

  • [ ] 使用 PDO 預處理語句,拼接佔位符而非數值
  • [ ] 嚴格驗證 ID:`ctype_digit` + 白名單過濾
  • [ ] CSRF Token:表單隱藏欄位 + Session 驗證
  • [ ] 權限檢查:確認當前用戶有刪除權限(RBAC/ACL)
  • [ ] 軟刪除:生產環境強烈建議,防誤刪、支援恢復
  • [ ] 審計日誌:記錄誰、何時、刪除了什麼
  • [ ] 前端確認對話框:雙重保險

結語

核取方塊批次刪除看似簡單,實則包含表單陣列傳遞、輸入驗證、SQL 注入防禦、事務一致性、軟刪除模式、審計追蹤、前端體驗優化等工程細節。掌握「佔位符動態生成 + PDO 事務 + 軟刪除」三板斧,即可構建安全、可維護、可擴展的批次操作功能。

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