PHP, MySQL, PDO-Transaktionen - Kann fetchAll () vor commit () kommen?

Weitere Fragen zur Transaktion!

Was ich gerade habe, ist ein Durcheinander von aufeinanderfolgenden Abfragen, die alle manuell rückgängig gemacht werden, wenn ein Fehler auftritt:

Code Block 1

$stmt1 = $db->prepare(...); // Update table1, set col=col+1
if($stmt1 = $db->execute(...)){

    $stmt2 = $db->prepare(...); // Insert into table2, id=12345
    if($stmt2 = $db->execute(...)){

        $stmt3 = $db->prepare(...); // Select val from table3
        if($stmt3 = $db->execute(...)){

            $result = $stmt3->fetchAll();
            if($result[0]['val'] == something){

                $stmt4 = $db->prepare(...); // Update table4, set status=2
                if($stmt4 = $db->execute(...)){

                    return true;

                }else{
                    $stmt1 = $db->prepare(...); // Update table1, set col=col-1 (opposite of above)
                    $stmt1 = $db->execute(...);

                    $stmt2 = $db->prepare(...); // Delete from table2, where id=12345 (opposite of above)
                    $stmt2 = $db->execute(...);

                    return false;
                }
            }

            return true;
        }else{
            $stmt1 = $db->prepare(...); // Update table1, set col=col-1 (opposite of above)
            $stmt1 = $db->execute(...);

            $stmt2 = $db->prepare(...); // Delete from table2, where id=12345 (opposite of above)
            $stmt2 = $db->execute(...);

            return false;
        }
    }else{
        $stmt1 = $db->prepare(...); // Update table1, set col=col-1 (opposite of above)
        $stmt1 = $db->execute(...);

        return false;
    }
}

Es ist ein Chaos, schwer zu debuggen, schwer zu ergänzen, schwer zu verstehen, wenn die Abfragen groß sind, und es werden nicht alle Tabellen auf den ursprünglichen Zustand zurückgesetzt, wenn die Verbindung auf halbem Weg unterbrochen wird.

Dieser Vorgang ist noch schlimmer, wenn eine Zeile gelöscht wird, da alles darin gespeichert werden muss - nur für den Fall, dass der Vorgang rückgängig gemacht werden muss.

Jetzt weiß ichdie meiste davon funktioniert immer noch, wenn ich es auf eine einzelne Transaktion portiere, aber der eine Teil, bei dem ich mir nicht sicher bin, ist:

Code Block 2

$result = $stmt3->fetchAll();
if($result[0]['val'] == something){
    ... continue ...
}else{
    ... reverse operations ...
    return false;
}

Weil die Ergebniserfassung vor dem @ stattfinden würcommit() in der Transaktion. Wie folgt

Code Block 3

$db->beginTransaction();    

try{
    $stmt1 = $db->prepare(...);
    $stmt1->execute();

    $stmt2 = $db->prepare(...);
    $stmt2->execute();

    $stmt3 = $db->prepare(...);
    $stmt3->execute();

    $result = $stmt3->fetchAll();
    if($result[0]['val'] == something){
        $stmt4 = $db->prepare(...);
        $stmt4->execute();
    }else{
        $db->rollBack();
        return false;
    }

    $db->commit();

    return true;
}catch(Exception $e){
    $db->rollBack();
    throw $e;
    return false;
}

Ob das funktioniert? Kann ich das$result = $stmt3->fetchAll(); Vo dascommit() und dann die bedingte Abfrage ausführen?

Auch da bin ich mir nicht ganz sicher, aber brauche ich das$db->rollBack(); innerhalb dertry Block, wenn der Code beendet wird return false) Vor demcommit()?

Antworten auf die Frage(2)

Ihre Antwort auf die Frage