Idén jag vanligtvis använder när jag arbetar med transaktioner ser ut så här (semi-pseudo-kod) :
try {
// First of all, let's begin a transaction
$db->beginTransaction();
// A set of queries; if one fails, an exception should be thrown
$db->query('first query');
$db->query('second query');
$db->query('third query');
// If we arrive here, it means that no exception was thrown
// i.e. no query has failed, and we can commit the transaction
$db->commit();
} catch (\Throwable $e) {
// An exception has been thrown
// We must rollback the transaction
$db->rollback();
throw $e; // but the error must be handled anyway
}
Observera att med denna idé, om en fråga misslyckas, måste ett undantag skapas:
- PDO kan göra det, beroende på hur du konfigurerar det
- Se
PDO::setAttribute
- och
PDO::ATTR_ERRMODE
ochPDO::ERRMODE_EXCEPTION
- Se
- annars, med något annat API, kanske du måste testa resultatet av funktionen som används för att köra en fråga och göra ett undantag själv.
Tyvärr är det ingen magi inblandad. Du kan inte bara lägga en instruktion någonstans och få transaktioner gjorda automatiskt:du måste fortfarande specificera vilken grupp av frågor som ska utföras i en transaktion.
Till exempel, ganska ofta kommer du att ha ett par frågor före transaktionen (innan begin
) och ytterligare ett par frågor efter transaktionen (efter antingen commit
eller rollback
) och du vill att dessa frågor ska köras oavsett vad som hände (eller inte) i transaktionen.