A ideia que geralmente uso ao trabalhar com transações é assim (semi-pseudo-código) :
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
}
Observe que, com essa ideia, se uma consulta falhar, uma exceção deve ser lançada:
- PDO pode fazer isso, dependendo de como você o configura
- Veja
PDO::setAttribute
- e
PDO::ATTR_ERRMODE
ePDO::ERRMODE_EXCEPTION
- Veja
- caso contrário, com alguma outra API, talvez seja necessário testar o resultado da função usada para executar uma consulta e lançar uma exceção por conta própria.
Infelizmente, não há mágica envolvida. Você não pode simplesmente colocar uma instrução em algum lugar e fazer transações automaticamente:você ainda precisa especificar qual grupo de consultas deve ser executado em uma transação.
Por exemplo, muitas vezes você terá algumas consultas antes da transação (antes do
begin
) e outras consultas após a transação (depois de commit
ou rollback
) e você vai querer que essas consultas sejam executadas não importa o que aconteceu (ou não) na transação.