Transações PHP, MySQL, DOP - O fetchAll () vem antes do commit ()?
Mais perguntas sobre transações!
O que tenho agora é uma bagunça de consultas agrupadas, que são todas revertidas manualmente, se houver alguma falha:
Bloco de código 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;
}
}
É uma bagunça, difícil de depurar, difícil de adicionar, difícil de entender quando as consultas são grandes e não retornará todas as tabelas ao estado original se a conexão for perdida no meio.
Esse mesmo processo é ainda pior ao excluir uma linha, porque tudo nela precisa ser armazenado - apenas no caso de a operação precisar ser desfeita.
Agora eu seia maioria disso ainda funcionará quando eu a portar para uma única transação, mas a única parte da qual não tenho certeza é:
Bloco de código 2
$result = $stmt3->fetchAll();
if($result[0]['val'] == something){
... continue ...
}else{
... reverse operations ...
return false;
}
Como a coleta de resultados seria realizada antes docommit()
na transação. Do seguinte modo:
Bloco de código 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;
}
Isso vai funcionar? Especificamente, posso incluir o$result = $stmt3->fetchAll();
antes acommit()
e, em seguida, execute a consulta condicional?
Além disso, não tenho muita certeza disso, mas preciso do$db->rollBack();
dentro dotry
bloco, se o código for encerrado (return false
) antes de ocommit()
?