A database transaction cannot roll back a filesystem move. Validate the upload, move it to a generated name, write the database row in a transaction, and delete the new file if the database operation fails.
Last updated: October 8, 2026.
<?php
declare(strict_types=1);
$tmp = $_FILES['image']['tmp_name'];
$mime = (new finfo(FILEINFO_MIME_TYPE))->file($tmp);
$extensions = ['image/jpeg' => 'jpg', 'image/png' => 'png'];
if (!isset($extensions[$mime])) {
throw new RuntimeException('Upload a JPEG or PNG image.');
}
$name = bin2hex(random_bytes(16)) . '.' . $extensions[$mime];
$path = __DIR__ . '/uploads/' . $name;
if (!move_uploaded_file($tmp, $path)) {
throw new RuntimeException('The upload could not be stored.');
}
try {
$pdo->beginTransaction();
$stmt = $pdo->prepare(
'INSERT INTO products (name, image_name) VALUES (:name, :image)'
);
$stmt->execute(['name' => $_POST['name'], 'image' => $name]);
$pdo->commit();
} catch (Throwable $error) {
if ($pdo->inTransaction()) {
$pdo->rollBack();
}
@unlink($path);
throw $error;
}Store the generated filename, never a client-supplied path. Prevent PHP execution in the upload directory.
Use compensation for the filesystem step
PDO can undo the row change, but it cannot undo move_uploaded_file(). Deleting the moved file in the exception handler compensates for failure. If deletion fails, log it for cleanup.
The PHP manual confirms that move_uploaded_file() verifies that the source came from an HTTP POST upload. The PDO transaction guide explains commit and rollback behavior. Neither replaces MIME inspection, authorization, or web-server restrictions.
Replace and delete images in the safe order
For an update, upload the replacement first, update the row, commit, and only then delete the old file. If the commit fails, remove the replacement and leave the old file intact. For deletion, commit the row change before removing the file. Queue failed cleanup for a later retry.
Keep the transaction limited to database work. Continue with the secure PHP upload pipeline, Fileinfo image validation, and creating WebP thumbnails.