批量刪除是後台管理常見功能,但原文代碼存在 SQL 注入、複選框值缺失、JS 確認邏輯缺失等多重問題。本文給出完整的前後端最佳實踐。
<form action="batch_delete.php" method="post" onsubmit="return confirmDelete()">
<table>
<thead><tr><th><input type="checkbox" id="checkAll"></th><th>標題</th></tr></thead>
<tbody>
<?php foreach ($newsList as $item): ?>
<tr>
<td><input type="checkbox" name="ids[]" value="<?= $item['id'] ?>" class="item-check"></td>
<td><?= htmlspecialchars($item['title']) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<button type="submit" name="batch_delete">批量刪除</button>
</form>
<script>
// 全選/反選
document.getElementById('checkAll').addEventListener('change', function() {
document.querySelectorAll('.item-check').forEach(cb => cb.checked = this.checked);
});
// 提交確認
function confirmDelete() {
const checked = document.querySelectorAll('.item-check:checked');
if (checked.length === 0) {
alert('請至少選擇一項!');
return false;
}
return confirm(`確定要刪除這 ${checked.length} 條記錄嗎?此操作不可恢復!`);
}
</script>
<?php
require_once 'db.php'; // PDO 連接
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['batch_delete'])) {
$ids = $_POST['ids'] ?? [];
// 1. 驗證:非空、全數字、去重
if (empty($ids)) {
die('未選擇任何記錄');
}
$ids = array_unique(array_filter($ids, 'ctype_digit'));
if (empty($ids)) {
die('無效的 ID 參數');
}
// 2. 構建 IN 佔位符
$placeholders = implode(',', array_fill(0, count($ids), '?'));
$sql = "DELETE FROM news WHERE news_id IN ($placeholders)";
try {
$pdo->beginTransaction();
$stmt = $pdo->prepare($sql);
$stmt->execute($ids); // 參數綁定,防注入
$affected = $stmt->rowCount();
$pdo->commit();
echo "成功刪除 $affected 條記錄";
// 建議:重定向回列表頁 header('Location: list.php'); exit;
} catch (PDOException $e) {
$pdo->rollBack();
error_log("Batch delete failed: " . $e->getMessage());
die('刪除失敗,請稍後重試');
}
}
?>
| 原問題 | 風險 | 修復方案 |
|---|---|---|
implode(',', $_POST['chk']) 直接拼接 SQL | SQL 注入 | PDO 預處理 + 參數綁定 |
複選框無 value 屬性 | 傳值為空字符串 | <input name="ids[]" value="= $id ?>"> |
| 無前端確認,點「取消」也可能提交 | 誤刪 | JS onsubmit="return confirmDelete()" 攔截 |
| 無事務,部分失敗數據不一致 | 數據完整性 | beginTransaction/commit/rollBack |
deleted_at 欄位,批量更新而非物理刪除,支持恢復。批量刪除看似簡單,安全、體驗、可維護性樣樣不能少。