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

PHP 批量刪除 Checkbox 多選數據:陣列轉 SQL IN 條件實作

     編輯:PHP 綜合知識

從表單多選到 SQL 批量刪除:陣列處理與安全構建

後台列表頁常見「勾選多行 → 批量刪除」需求。前端用同名 name="ids[]" 發送陣列,後端需將陣列安全轉為 SQL IN (...) 條件。本文展示完整流程與防注入要點。

前端表單結構

<form action="?action=doing" method="post">
    <input name="ID_Dele[]" type="checkbox" value="1"/> 項目 1
    <input name="ID_Dele[]" type="checkbox" value="2"/> 項目 2
    <input name="ID_Dele[]" type="checkbox" value="3"/> 項目 3
    <input name="ID_Dele[]" type="checkbox" value="4"/> 項目 4
    <input type="submit" value="批量刪除"/>
</form>

瀏覽器將勾選的值作為陣列提交:$_POST['ID_Dele'] = ['1','2','3']。

後端處理核心代碼

<?php
if ($_GET['action'] === 'doing' && $_POST) {
    // 1. 獲取陣列(未勾選時可能為 null)
    $ids = $_POST['ID_Dele'] ?? [];

    // 2. 過濾驗證:確保全為整數 ID
    $ids = array_map('intval', $ids);           // 強制轉整數,過濾非數字
    $ids = array_filter($ids, fn($v) => $v > 0); // 移除 0 或負數
    $ids = array_unique($ids);                   // 去重

    if (empty($ids)) {
        die('未選擇有效項目');
    }

    // 3. 安全構建 IN 條件:佔位符動態生成
    $placeholders = implode(',', array_fill(0, count($ids), '?'));
    $sql = "DELETE FROM `doing` WHERE `id` IN ($placeholders)";

    // 4. 預處理語句綁定參數(防 SQL 注入)
    $stmt = $pdo->prepare($sql);
    $stmt->execute($ids);

    echo "成功刪除 {$stmt->rowCount()} 條記錄";
}
?>

關鍵點解析

  1. 陣列接收:name="ID_Dele[] 方括號告訴 PHP 將同名字段組裝為陣列,ASP 直接給字串 1,2,3,PHP 需額外處理。
  2. 白名單過濾:intval + > 0 確保只有合法正整數進入 SQL,徹底阻斷注入。
  3. 佔位符動態生成:array_fill(0, count($ids), '?') 產生 ['?','?','?'],implode 拼成 ?,?,?,數量與參數嚴格對應。
  4. PDO 預處理:execute($ids) 自動綁定陣列值到佔位符,無需手動 bindValue 循環。

對比:原碼的不安全寫法

// ❌ 危險:直接拼接字串,若 $ids 含惡意輸入將導致注入
$ID_Dele = implode(",", $_POST['ID_Dele']);
$SQL = "delete from `doing` where id in ($ID_Dele)";

若攻擊者構造提交 ID_Dele[]=1; DROP TABLE users;--,經 implode 後 SQL 變為:

DELETE FROM `doing` WHERE id IN (1; DROP TABLE users;--)

雖多語句執行受驅動限制,但聯合查詢、子查詢注入風險極高。

擴展:大批量刪除優化

// 若 ID 連續或量極大 (萬級+),考慮分塊或臨時表
// 方案 A:分塊執行,避免單條 SQL 過長 / 鎖表過久
$chunks = array_chunk($ids, 500);
foreach ($chunks as $chunk) {
    $ph = implode(',', array_fill(0, count($chunk), '?'));
    $pdo->prepare("DELETE FROM `doing` WHERE `id` IN ($ph)")->execute($chunk);
}

// 方案 B:臨時表 + JOIN(適合極大批量、需事務一致性)
$pdo->exec('CREATE TEMPORARY TABLE tmp_del (id INT PRIMARY KEY)');
$stmt = $pdo->prepare('INSERT INTO tmp_del (id) VALUES (?)');
foreach ($ids as $id) { $stmt->execute([$id]); }
$pdo->exec('DELETE d FROM `doing` d JOIN tmp_del t ON d.id = t.id');

前端體驗優化

  • 全選/反選 Checkbox:<input type="checkbox" id="checkAll"> + JS 同步子項狀態。
  • 提交前確認:onclick="return confirm('確定刪除選中的 ' + checkedCount + ' 項?')"。
  • AJAX 異步刪除:fetch('/api/delete', {method:'POST', body: JSON.stringify(ids)}),無刷新更新列表。

批量刪除看似簡單,實則是「前端陣列傳輸 → 後端白名單過濾 → 參數化查詢」安全鏈路的經典練習。養成預處理習慣,讓 SQL 注入無處遁形。

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