Uncaught exception ‘PDOException’ with message ‘There is no active transaction’
というのが出てずっと原因不明だったけど動くから放っておいたけどなんとなく原因がわかった。
ずっと以下のようなコードにしていた
try{ $db->beginTransaction(); // 処理 $db->commit(); } catch(PDOException $e){ $db->rollback(); }
でもbeginTransaction()でエラーになった場合トランザクションはないのでrollback()するとエラーになるのは当然。
さらにいうとrollback()エラーになることもあるだろうからこのときは現状ではスルーされる。
そんなわけでまずtry-catchを2つにして、
beginTransaction()は一つ目のtry-catchで行う。
実際の処理やcommit(),rollback()は2つ目のtry-catchの中で行う。
rollback()での例外は1つ目のtry-catchで拾うようにする。
try{ $result = $db->beginTransaction(); if($result==false) throw new PDOException(“beginTransaction failure"); try{ // 処理 $db->commit(); } catch(PDOException $e){ $db->rollback(); throw $e; } } catch(Exception $e){ }
ただPDOを直で触るより以下のような関数を持ったラッパークラスを作ってやれば最初みたいな使い方をしても無駄にrollback()されないしbeginTransaction()し忘れも検出できるからこっちの方が見通しがいいかな。
// transaction開始 public function start_trans(){ $result = $this->db->beginTransaction(); if($result==false){ throw new PDOException(“beginTransaction failure”); } $this->in_transaction = true; } // トランザクション終了(コミット) public function end_trans(){ if($this->in_transaction==false){ throw new PDOException(“Transaction is not begun !!”); } $this->db->commit(); $this->in_transaction = false; } // ロールバック public function rollback(){ if($this->in_transaction){ $this->db->rollback(); $this->in_transaction = false; } }
こんなんどうでしょう。