2016-12-30 5 views
2

PHPスクリプトのトランザクションに問題があります。私は複数のクエリを作成し、少なくとも1つが失敗した場合にそれらをすべて呼び出すことができるようにしたいと思います。スクリプトの簡単な例を見ることができます私が使用しています:私はライン消去するとPHP PDO - アクティブなトランザクションがありません

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

:今

$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(); 

は、この例では、エラーが発生し $ conn->ロールバックを() ; エラーが表示されなくなるため、pdoオブジェクトが開いているトランザクションを表示できない理由を理解できません(begintransactionとcommitはエラーを生成しません)。私もトランザクション内にrollBack()を入れてみましたが、違いはありませんでした。私はまだ 'アクティブな取引はありません。

私はInnoDB上でPHP 5.6およびMysqlテーブルを実行しています。

+2

あなたがここにトランザクションをコミットしている: '$ RES1 = $ conn->は(コミット);'あなたが第一の例のようにのtry-catchステートメントにトランザクションコードをラップ – e4c5

+0

試みをロールバックすることはできませんので、 http://php.net/manual/en/pdo.transactions.php –

+0

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

答えて

2

try-catchステートメント内にトランザクションコードをラップします。答えの

//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

本当によくベースとストレートフォワードな説明をコメントとしてRichardによって提供されました。

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

こんにちは、ありがとう、迅速な答えです。それは動作するようです!しかし、私はなぜそうは分かりません。 try/catchブロックなしでトランジションを使用することは不可能ですか?さらに、私はコードから取り除こうとしたときに、ロールバックは無関係であると思うし、データベースに新しいレコードをもらっていない(これはアイデアだが、なぜ起こっているのかわからない) – user1857756

+0

同じ@ e4c5がコメントに書いた理由。私はそれがあなたの問題メリークリスマスを解決してうれしいです:) –

+1

ちょうどこれに追加する、あなたがエラーを持っている理由は、それがすでに閉じていたときにトランザクションを閉じるしようとしたためです。 "beginTransaction"が1つ開き、 "rollBack"または "commit"で閉じます。 単一の "beginTransaction"ステートメントの両方でコミット/ロールバックを行わないでください。そうしないとエラーが発生します。 上記のtry/catchコードは、1つの "closing"文が実行されることを保証します。 –

関連する問題