79786720

Date: 2025-10-09 18:01:57
Score: 1.5
Natty:
Report link

Solutions :

Either all changes happen, or none do (It avoids leaving the system in a half-changed state)

1 - Backup folder :
It script that if any step fails, everything is rolled back to its original state using a backup folder.

Rollback Logic : Backup the Original File and Directory, Creates a subfolder inside the backup folder, Copies the original file into that subfolder. Deletes the backup file and folder since everything succeeded.

<?php

//there is a folder that cannot be registered as an account.
$backupfolder = 'backupfolder';

$oldname = $_SESSION['oldname'];
$newname = $_POST['newname'];

$oldFile = "./$oldname/$oldname.php";
$newFile = "./$oldname/$newname.php";

$oldDir = "./$oldname";
$newDir = "./$newname";

mkdir("$backupFolder/$oldname");
copy($oldFile, "$backupFolder/$oldname/$oldname.php");

if (file_exists($oldFile) && rename($oldFile, $newFile)) {

    if (file_exists($oldDir) && rename($oldDir, $newDir)) {

        try {
            $conn->beginTransaction();

            $update1 = $conn->prepare("UPDATE table1 SET name=? WHERE name=?");
            $update1->execute([$newname, $oldname]);

            $update2 = $conn->prepare("UPDATE table2 SET name=? WHERE name=?");
            $update2->execute([$newname, $oldname]);

            if ($update1->rowCount() > 0 && $update2->rowCount() > 0) {
                $conn->commit();

                unlink("$backupFolder/$oldname/$oldname.php");
                rmdir("$backupFolder/$oldname");

                echo 'changed !';
            } else {
                throw new Exception();
            }

        } catch (Exception $e) {

            $conn->rollBack();
            rename($newDir, $oldDir);
            copy("$backupFolder/$oldname/$oldname.php", $oldFile);
            echo 'didnt change !';
        }

    } else {

        copy("$backupFolder/$oldname/$oldname.php", $oldFile);
        echo 'didnt change !';
    }

} else {

    copy("$backupFolder/$oldname/$oldname.php", $oldFile);
    echo 'didnt change !';
}
?>

2 - Flags for Tracking Progress :
it uses a flags array to track which steps succeed.

Rollback Logic : If the database update fails, It checks if the directory was renamed and renames it back, It checks if the file was renamed and renames it back.

<?php

$oldname = $_SESSION['oldname'];
$newname = $_POST['newname'];

$oldFile = "./$oldname/$oldname.php";
$newFile = "./$oldname/$newname.php";

$oldDir = "./$oldname";
$newDir = "./$newname";

$flags = [
    'file_renamed' => false,
    'dir_renamed' => false,
    'db_updated' => false
];


if (file_exists($oldFile) && rename($oldFile, $newFile)) {
    $flags['file_renamed'] = true;

    if (file_exists($oldDir) && rename($oldDir, $newDir)) {
        $flags['dir_renamed'] = true;

        try {
            $conn->beginTransaction();

            $update1 = $conn->prepare("UPDATE table1 SET name=? WHERE name=?");
            $update1->execute([$newname, $oldname]);

            $update2 = $conn->prepare("UPDATE table2 SET name=? WHERE name=?");
            $update2->execute([$newname, $oldname]);

            if ($update1->rowCount() > 0 && $update2->rowCount() > 0) {

                $conn->commit();
                $flags['db_updated'] = true;
                echo 'changed !';
            } else {

                throw new Exception();
            }

        } catch (Exception $e) {

            $conn->rollBack();
        }
    }
}


if (!$flags['db_updated']) {

    if ($flags['dir_renamed']) {
        rename($newDir, $oldDir);
    }

    if ($flags['file_renamed']) {
        rename($newFile, $oldFile);
    }

    echo 'didnt change !';
}
?>

NOTE : The flags-based approach performs fewer physical operations on the file system, which means it's less prone to errors and generally faster.

with contributions from @adyson and @masoudiofficial

Reasons:
  • Contains signature (1):
  • Long answer (-1):
  • Has code block (-0.5):
  • User mentioned (1): @adyson
  • User mentioned (0): @masoudiofficial
  • Self-answer (0.5):
  • Low reputation (0.5):
Posted by: masoudiofficial