75 PDO5 transazioni
Immaginiamo di dover fare un po’ di pulizia, cancellando i questionari più vecchi di tot anni e poi cancellare gli utenti iscritti prima di tale data e con zero privi di questionari svolti.
Sarebbero 2 operazioni di delete, la cancellazione questionari e quella utenti. Supponiamo che per qualsiasi motivo lo script inizia e prima di terminare si blocca, si tratta di casi chiamati di perdita di consistenza a causa di operazioni non completate. Il meccanismo transazionale è stato introdotto per ovviare a tali inconvenienti. Le transazioni sono uno script di comandi SQL per cui il sistema che le esegue assicura che o tutte quelle operazioni dello script vengano eseguite correttamente, oppure che è in grado di accorgersi dell’anomalia riportando la situazione allo stato precedente all’esecuzione (roll back del database).
Saltando la solita parte di inclusione e connessione vediamo ora la parte delle transaction della nuova pagina transazione_PDO.php. Il supporto per le transazione di MySQL supporta perfettamente il try/catch del php.
Iniziamo una transazione col metodo beginTransaction:
try { $conn->beginTransaction();
Prepariamo poi il comando che canchella i questionari anteriori al primo gennaio 2002:
$comandoSQL ="delete from questionari_svolti where fine<'2002-01-01'";
Lo eseguiamo col metodo exec, da usare quando non ci si aspetta un ritorno di risultato di righe.
Stessa cosa per gli utenti:
$comandoSQL = "delete from users where iduser not in ". "(select fkuser from questionari_svolti)"; $conn->exec($comandoSQL);
Tra il primo comando e il secondo potrebbere verificarsi una anomalia che blocca l’esecuzione, avendo istanziato una transazione, i dati sul database non vengono cancellati permanentemente, fino a quando non viene eseguita la conferma tramite il comando commit:
$conn->commit();
Se viene eseguita questa riga, le operazioni sono andate a buon fine e le modifiche vengono rese permanenti. Se avviene l’anomalia, il blocco try si interrompe, insieme al comando commit e si passa al blocco catch:
catch (Exception $e) { $conn->rollBack(); echo "Pulizia archivi fallita ".$nl; die(); }
Con il rollback il database viene riportato allo stato precedente.
Di seguito il codice completo della pagina:
<?php include($_SERVER['DOCUMENT_ROOT']."/fagtest/my_include/setup_con_DB.php"); //recupero credenziali da file ESTERNO alla cartella pubblica del sito try { //CONNESSIONE $conn = new PDO("mysql:host=localhost;dbname={$accessData['dbname']}", $accessData['username'],$accessData['password']); } catch (PDOException $e) { echo $e->getMessage() . "<br/>"; echo "Connessione al server fallita. Impossibile procedere. Contattare ..."; die(); } //ATTIVAZIONE ECCEZIONI PER METODO QUERY $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); try { $conn->beginTransaction(); $comandoSQL ="delete from questionari_svolti where fine<'2002-01-01'"; $conn->exec($comandoSQL); //dopo l'esecuzione del precedente comando e quella del seguente //potrebbere verificarsi una anomalia che blocca l'esecuzione //sul server ... //verrebbe sollevata l'eccezione, saltato il commit e comandato il rollback //controlli ... /* $errore=true; if($errore) $conn->rollBack(); //annulliamo le operazioni precedenti else { $comandoSQL = "delete from users where iduser not in ". "(select fkuser from questionari_svolti)"; $conn->exec($comandoSQL); //se siamo arrivati qui rendiamo permanenti le modifiche $conn->commit(); } */ $comandoSQL = "delete from users where iduser not in ". "(select fkuser from questionari_svolti)"; $conn->exec($comandoSQL); //se siamo arrivati qui rendiamo permanenti le modifiche $conn->commit(); } catch (Exception $e) { $conn->rollBack(); echo "Pulizia archivi fallita ".$nl; die(); } //CHIUDIAMO LA CONNESSIONE E LIBERIAMO LE RISORSE OCCUPATE ... $conn=null;