2016-12-30 3 views
2

Ich habe Probleme mit Transaktionen in PHP-Skript. Ich möchte mehrfache Abfragen durchführen und sie alle abrufen können, wenn mindestens einer von ihnen fehlschlägt. Im Folgenden finden Sie ein einfaches Beispiel für das Skript finden Ich verwende:PHP PDO - Es gibt keine aktive Transaktion

Uncaught exception 'PDOException' with message 'There is no active transaction'

Wenn ich die Zeile löschen: $ conn-> rollback()

$tags_input = array(6,4,5); 
$conn = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8', 
DB_USER, DB_PASSW, array( 
    PDO::ATTR_EMULATE_PREPARES => false, 
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'")); 

    $conn->beginTransaction(); 

    $sql = "INSERT INTO projects (id, pr_id, enabled) VALUES (:val0, :val1, :val2)"; 
    $stmt = $conn->prepare($sql); 
    if(count($tags_input)>0){ 
      for($i = 0;$i<count($tags_input);$i++){ 
        $stmt->bindValue(':val0', 57); 
        $stmt->bindValue(':val1', $tags_input[$i]); 
        $stmt->bindValue(':val2', 'Y'); 
        $result = $stmt->execute(); 

      } 

    } 

    $res1 = $conn->commit(); 
    $conn->rollBack(); 

nun dieses Beispiel einen Fehler erzeugt ; Der Fehler verschwindet, daher kann ich nicht verstehen, warum pdo-Objekt keine offene Transaktion sehen kann (Begintransaction und Commit erzeugen keine Fehler). Ich habe auch versucht, rollBack() innerhalb der Transaktion zu setzen, machte aber keinen Unterschied. Ich habe immer noch einen Fehler erhalten. Es gibt keine aktive Transaktion.

Ich verwende PHP 5.6 und Mysql Tabellen auf InnoDB.

+2

Du commiting die Transaktion hier: '$ res1 = $ conn-> commit();', so dass Sie nicht – e4c5

+0

versuchen Rollback können Sie Ihren Transaktionscode zu einer Try-catch-Anweisung wie im ersten Beispiel Einwickeln in http://php.net/manual/de/pdo.transactions.php –

+0

https://phpdelusions.net/pdo#transactions –

Antwort

2

Wickeln Sie Ihren Transaktionscode in eine Try-Catch-Anweisung.

//try { 
$tags_input = array(6,4,5); 
$conn = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8', 
DB_USER, DB_PASSW, array( 
    PDO::ATTR_EMULATE_PREPARES => false, 
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'")); 
} catch (Exception $e) { 
    die("Unable to connect: " . $e->getMessage()); 
}  
try { 
    $conn->beginTransaction(); 
    $sql = "INSERT INTO projects (id, pr_id, enabled) VALUES (:val0, :val1, :val2)"; 
    $stmt = $conn->prepare($sql); 
    if(count($tags_input)>0){ 
      for($i = 0;$i<count($tags_input);$i++){ 
        $stmt->bindValue(':val0', 57); 
        $stmt->bindValue(':val1', $tags_input[$i]); 
        $stmt->bindValue(':val2', 'Y'); 
        $result = $stmt->execute(); 
      } 
    } 
$res1 = $conn->commit();  
} catch (Exception $e) { 
    $conn->rollBack(); 
    echo "Failed: " . $e->getMessage(); 
} 

EDIT

Ein wirklich gut basierte und geradlinig Erläuterung der Antwort wurde von Richard als Kommentar zur Verfügung gestellt.

The reason you got error is because you were trying to close a transaction when it was already closed. beginTransaction opens one, and EITHER rollBack OR commit closes it. You have to avoid doing BOTH actions, meaning commit/rollback, for a single beginTransaction statement, or you'll get an error. The above try/catch code ensures that only one closing statement is executed.

+0

Hallo, Vielen Dank für die schnelle Antwort. Es scheint zu funktionieren! Ich bin mir jedoch nicht sicher warum. Ist es unmöglich, Transaktionen ohne try/catch-Block zu verwenden? Darüber hinaus denke ich Rollback hier ist irrelevant, als ich versuchte, es aus dem Code zu nehmen und auch keine neuen Datensätze in der Datenbank (was die Idee war, aber nicht sicher, warum es passiert) – user1857756

+0

Es ist für das gleiche Grund wie @ e4c5 schrieb in einem Kommentar. Ich bin froh, dass es Ihr Problem gelöst hat, frohe Weihnachten :) –

+1

Nur um hinzuzufügen, der Grund, warum Sie Fehler haben, ist, weil Sie versuchten, eine Transaktion zu schließen, wenn es bereits geschlossen wurde. "beginTransaction" öffnet eine, und entweder "rollBack" oder "commit" schließt es. Sie müssen vermeiden, BEIDE eine Festschreibung/Rollback für eine einzelne "beginTransaction" -Anweisung, oder Sie erhalten einen Fehler. Der obige try/catch-Code stellt sicher, dass NUR 1 "closing" -Anweisung ausgeführt wird. –

Verwandte Themen