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

PHP 刪除資料庫記錄同步刪除實體圖片檔案

     編輯:PHP 綜合知識

核心邏輯:資料庫與檔案系統原子性處理

刪除記錄時,必須同時清理關聯的上傳檔案,避免孤兒檔案佔用空間。

完整實作範例

<?php
// 資料庫連線(建議改用 PDO)
$conn = mysql_connect('127.0.0.1', 'root', 'root') or die('DB 連線失敗');
mysql_select_db('test', $conn);
mysql_query("SET NAMES 'utf8'");

// 假設表結構:id, title, litpic (儲存相對路徑)
$sql = "SELECT id, litpic FROM test1";
$query = mysql_query($sql) or die(mysql_error());

if (mysql_num_rows($query)) {
    while ($rs = mysql_fetch_assoc($query)) {
        // 先刪除資料庫記錄
        $delSql = "DELETE FROM test1 WHERE id = " . (int)$rs['id'];
        if (mysql_query($delSql)) {
            // 再刪除實體檔案
            if (deleteFile($rs['litpic'])) {
                echo "ID {$rs['id']}:記錄與圖片皆刪除成功<br>";
            } else {
                echo "ID {$rs['id']}:記錄刪除成功,但圖片刪除失敗(可能檔案不存在)<br>";
            }
        } else {
            echo "ID {$rs['id']}:資料庫刪除失敗 - " . mysql_error() . "<br>";
        }
    }
} else {
    echo "無資料可刪除";
}

function deleteFile($path) {
    // 安全檢查:防止路徑遍歷攻擊
    $path = realpath($path);
    $uploadDir = realpath(__DIR__ . '/uploads');
    if ($path === false || strpos($path, $uploadDir) !== 0) {
        return false; // 路徑不在允許目錄下
    }
    
    if (is_file($path)) {
        return @unlink($path);
    }
    return false; // 不存在或非檔案
}

關鍵安全考量

風險防護措施
路徑遍歷 (../../../etc/passwd)realpath() 正規化 + 檢查是否在上傳目錄下
SQL Injection使用 (int)$id 或 Prepared Statement
刪除失敗無感知檢查 unlink() 回傳值並記錄日誌
資料庫刪除成功但檔案刪除失敗記錄異常、人工介入或排程掃描孤兒檔案
並發刪除競態資料庫交易 + 檔案鎖 (flock) 或軟刪除欄位

進階模式:軟刪除 + 非同步清理

// 1. 資料表加欄位:deleted_at TIMESTAMP NULL, file_deleted TINYINT DEFAULT 0
// 2. 刪除請求只更新標記
UPDATE test1 SET deleted_at = NOW() WHERE id = ?;

// 3. 背景 Worker 定期掃描
SELECT id, litpic FROM test1 WHERE deleted_at IS NOT NULL AND file_deleted = 0;
// 4. 刪除檔案成功後更新
UPDATE test1 SET file_deleted = 1 WHERE id = ?;

優點:回應快速、可復原、避免長時間交易鎖定資料表。

現代化 PDO 版本

<?php
$pdo = new PDO('mysql:host=127.0.0.1;dbname=test;charset=utf8mb4', 'root', 'root');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$stmt = $pdo->query("SELECT id, litpic FROM test1");
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    $pdo->beginTransaction();
    try {
        $pdo->prepare("DELETE FROM test1 WHERE id = ?")->execute([$row['id']]);
        if (deleteFile($row['litpic'])) {
            $pdo->commit();
        } else {
            $pdo->rollBack();
            error_log("檔案刪除失敗,已回滾資料庫:{$row['litpic']}");
        }
    } catch (Exception $e) {
        $pdo->rollBack();
        error_log($e->getMessage());
    }
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved