cakephpでのトランザクション処理について

このQ&Aのポイント
  • cakephpでのトランザクション処理についての質問です
  • 注文番号を重複させずに採番する方法について知りたい
  • cakephpでトランザクション処理をする方法を教えてください
回答を見る
  • ベストアンサー

cakephpでのトランザクション処理について

このカテゴリには初めて投稿いたします。 どうにも解決ができないため、質問させていただきました。 cakephpで、注文番号の連番発行のために、今回初めてトランザクション処理が必要なケースが出てきまして、 ネットで検索して出て来る情報を元に、そのとおりに記述しているのですが、どうやってもうまく行きません。 DBのテーブルはInnoDBになっています。 参考にしたサイトは例えば http://wataame.sumomo.ne.jp/archives/3812 などです。 --------------------実際のコード -----以下はあるモデル内(ここでは、SamplemodelDataとしています)に記述した関数での処理です。$thisはそのモデルを示します。 $dataSource = $this->getDataSource(); $dataSource->begin($this); $res = $this->find('first',array('conditions'=>array('classification'=>$classification,'commoncode'=>$commoncode))); if($this->getNumRows()==0){//レコードなしの場合 $returnNumber = 1; $this->save(array('classification'=>$classification, 'commoncode'=>$commoncode, 'number'=>1)); }else{ $res['ExsamplemodelData']['number'] += 1; $returnNumber = $res['SamplemodelData']['number']; $this->set('id', $res['SamplemodelData']['id']); $this->saveField('number', $returnNumber); } $dataSource->commit($this); return $returnNumber; -------------------- ■目的 ユーザーが同時刻に何人同時に注文しようと、注文番号を重複させずに注文番号を採番することが目的です。 極端なことを言えば、ある同じ時刻(秒まで一緒)に世界各国から100人同時に全く同じタイミングで注文が入っても、注文番号を重複させないようにしたいです。 ※DBのシリアルを使えば確実に重複させないようにできることは知っています。しかし、今回は単純に連番だけでなくいろいろなケースにおいて意味をもつ文字列も付与したものをプライマリキーとしているので、単純なシリアルではだめなのです。 ■うまくいかない点 ・上記の記述でも、トランザクション自体は機能しているようです。  最後の $dataSource->commit($this); をコメントアウトにすると、DBの番号が永遠にインクリメントされませんので。 ・begin ~ commit までの間に、他のスレッドで、 $this->find('first',array('conditions'=>array('classification'=>$classification,'commoncode'=>$commoncode))); が実行されると、インクリメントされる前の番号が返されるのです。 =>それよりも前のスレッドが begin をした瞬間からcommitするまでは、他のスレッドでfindしても、待ち状態になって欲しいのです。 ・検証用プログラムで、上記の処理を、2つのブラウザから同時に100回繰り返す(2つ併せて200回繰り返し処理させる)と、 毎回200件中、5~7件程度、番号が重複してしまいます。 ■質問内容 ・このような精度を求めるようなケースでは、cakephpでトランザクション処理をしても、もともと無理な要望なのでしょうか? ・上記の記述で不足している部分は何でしょうか?例えば、mysqlのトランザクションには他スレッドから、updateだけを禁止にする指定と、updateとselectも禁止にする指定ができるようですが、上記の記述だと他スレッドではupdateしか禁止されていないために、selectであるfindは待ちが発生しないということなのでしょうか?しかし、selectも禁止にするとかそういう指定方法がどう探してもそういう情報が見つけられませんでした。 要約すると、つまり、 「cakephpでトランザクション処理(beginからcommitの間は、他スレッドからはupdateもselectも禁止)にする方法はどうやったらよいのでしょうか?」 ということでございます。 ご存じの先生方、是非、お力お貸しいただけますでしょうか。 何卒よろしくお願いいたします。

  • PHP
  • 回答数2
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
  • mpro-gram
  • ベストアンサー率74% (170/228)
回答No.2

find('first', のとき、降順設定しないと、取得する先頭1行目は最小値だけど、そこは設定してますか? ちゃんと最大値を得るようになっていたとして、あとは、cakePHPよりは、MySQL innodb の問題じゃないかな。 http://dev.mysql.com/doc/refman/5.1/ja/innodb-locking-reads.html innodb のtransaction は、defaultは REPEATABLE READ で、select 文でのデータ取得時は、他者に読み書き可能なので、これを防ぐには、先に発行される select文に for update が必要です。これで、他者の読み書きをブロックします。 Modelの findメソッドでは、それを追加するすべはないので(接続先データベースによって対応の違う物は実装されていない) よって、 Model->query(string $sql ,array $placedata) メソッドで直接SQL文を渡して実行することになります。 プレースホルダーも使えるので、pdoでのプレースホルダー指定方法に則って作成するとよいです。 SQL例 SELECT max( number ) as number FROM exsample_models where classification=? and commoncode=? FOR UPDATE;

futsuunohito
質問者

お礼

mpro-gram様 詳細のご指南ありがとうございました。 いただいた情報にて、全て解決することができました。 すべては、mpro-gram様のご回答のおかげでございます。 検証で1000回繰り返し×3ブラウザで同時 で合計3000回処理させても1件も重複しなくなりました! (別途、Model->queryで検証した際に2回目以降の同じクエリだとキャッシュが有効になることを知らなかったため、少し嵌ってしまいましたが、それも方法が分かり解消できました。) cakephpの標準コードだけでは、for updateの完全な排他制御はできないのですね。 本当に感謝申し上げます。

その他の回答 (1)

  • kikanbo
  • ベストアンサー率31% (44/139)
回答No.1

トランザクション処理は他からの更新をロックする機能ではないから。。。

関連するQ&A

  • insert1つの処理でもトランザクションは必要?

    お世話になります。 現在、MYSQLデータベースを使用したプログラムを書いており、 そこでトランザクションについて質問があります。 トランザクションとは、複数の処理がすべて成功した場合に正式な処理を実行(commit)、1つでも失敗した場合は元に戻す(rollback)というようなことかと思うのですが、 では、1つの処理のみの場合は、トランザクションを使用する必要はないのでしょうか? 例えば、 ・あるテーブルにデータをinsertしたい。 このような単一の処理を書く場合でも、 以下のようにトランザクションを使うべきでしょうか? $dsn = 'mysql:dbname=〇〇〇;host=〇〇〇;charset=utf8'; $user = 'user'; $pwd = 'pwd'; //DB接続 try { $pdo = new PDO($dsn, $user, $pwd); } catch (PDOException $e) { die('DB接続失敗'); } //トランザクション開始 $pdo->beginTransaction(); //INSERT try { $sql = 'INSERT into table (test1, test2, test3) VALUES (:a, :b, :c)'; $st= $pdo->prepare($sql); $ret = $st->execute(array( ':a' => $a, ':b' => $b, ':c' => $c, )); if (!$ret) { throw new Exception('INSERT 失敗'); } //commit $pdo->commit(); } catch (PDOException $e) { //rollback $pdo->rollBack(); } $pdo = null; ※前提として、テーブルを使用するユーザーは多数います。 ご存知の方、ご回答いただけるれば幸いです。 よろしくお願い致します。

    • ベストアンサー
    • PHP
  • ActiveX DLLでのオラクルのトランザクション

    VB6とOracle9iのOO4Oにてシステムを構築しておりますが、一つ解らないことがありましたので、どなたかご教授願います。 あるPG(通常のEXEです)よりActiveX DLLを呼び出してOracleの表へデータを挿入する処理があります。呼び出し元となる通常のEXEはまずOracleの接続処理を記述しています。正常に接続が完了したならトランザクションを開始し、表のDeleteを実行します。その後ActiveX DLLを呼び出して表のInsertを実行しています。再び通常のEXEに制御が戻り、トランザクションの完了(COMMIT)または破棄(ROLLBACK)を行います。しかし、最後のトランザクションのCOMMIT(ROLLBACK)を行うと『コッミト(ロールバック)時にアクティブなトランザクションがありません』というエラーが発生してしまいます。正しくBegin Transactionを実行しているのに、これはどういうこと何のでしょうか。ご存知の方がいらっしゃましたら教えてください。

  • トランザクション名の付け方

    こんにちは。VB.NETの勉強をしている社会人です。 クリック時にトランザクション名が付されるようにコーディングしているのですが、誤りがあるようでうまく動作しません。「 sTrans = scn.BeginTransaction("トランザクション1")」の記述に問題があるようですが、記述はテキストのままです。 ※「sTrans = scn.BeginTransaction()」と、名前を付けなければトランザクションは実行されます。 どのようにすればトランザクションに名前が付けられるのか、教えていただけないでしょうか。 よろしくお願いいたします。 Public Class Form1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim sTrans As OleDb.OleDbTransaction Dim scn As OleDb.OleDbConnection = New OleDb.OleDbConnection( _ "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" _ & "C:\VB_DB\SampleDB2.mdb;Persist Security Info=False") scn.Open() 'トランザクションを開始する Try sTrans = scn.BeginTransaction("トランザクション1") MessageBox.Show("トランザクションを開始しました。", "処理経過") 'トランザクションを終了する sTrans.Commit() Catch ex As Exception MessageBox.Show("トランザクションを開始できませんでした。", "処理結果") End Try scn.Close() End Sub End Class

  • トランザクション処理

    トランザクション処理で、 1.カートの数量を使って商品の在庫数を減算する 2.foreachを使って1商品ずつ取り出し、該当する在庫数を減算する 3.ログインユーザーのカート情報を削除する の処理を行うには以下のコードをどのように修正すればいいですか? phpmyadminで作成したテーブル情報は以下の通りです。 cartテーブル(ユーザがカートに追加した商品の情報)が cart_id, user_id, item_id, amount, create_date, update_date productテーブル(商品情報)が id, name, price, img, status, create_date, update_date item_stockテーブル(在庫情報)が stock_id, item_id, stock, create_date, update_date です。 $dbh->beginTransaction(); // トランザクション開始 // cartテーブルとitem_stockテーブル try { // 現在ログインしているユーザーのカート情報を削除する $sql = 'DELETE FROM cart WHERE user_id = ?'; $stmt = $dbh->prepare($sql); $stmt->bindValue(1, $user_id, PDO::PARAM_INT); $stmt->execute(); foreach ($data as $key => $rec) { $stock = (int)$rec['stock'] - (int)$rec['amount']; } // 在庫テーブルを更新 // カートの数量を使って商品の在庫数を減算する // foreachで1商品ずつ取り出し、該当する在庫数を減算する $sql = 'UPDATE item_stock SET stock = ?, update_date = ? WHERE item_id = ?'; $stmt = $dbh->prepare($sql); $stmt->bindValue(1, $stock, PDO::PARAM_INT); $stmt->bindValue(2, $date, PDO::PARAM_STR); $stmt->bindValue(3, $item_id, PDO::PARAM_INT); $stmt->execute(); $carts = $dbh->commit(); $success_msg[] = '在庫数を更新しました。'; } catch (PDOException $e) { // ロールバック処理 $dbh->rollback(); $err_msg[] = '在庫数の更新に失敗しました。' . $e->getMessage(); }

    • 締切済み
    • PHP
  • cakePHPのエラー

    Error: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'validateSearch' at line 1 SQL Query: validateSearch Notice: If you want to customize this error message, create app/View/Errors/pdo_error.ctp というエラーが出て困っています。 validateSearchの付近を確認してもよくわかりません。 searchpluginを使っているのですが、上手くいきません。 コントローラーは、 <?php App::uses('AppController', 'Controller'); class Mac554FoodDatasController extends AppController { public $name='Mac554FoodDatas'; public $components =array('Search.Prg'); public $presetVars=array(); public function beforeFilter() { //検索対象のフィールド設定代入 $this->presetVars = $this->Mac554FoodData->presetVars; // ページャ設定 $pager_numbers = array( 'before' => ' - ', 'after'=>' - ', 'modulus'=> 10, 'separator'=> ' ', 'class'=>'pagenumbers' ); $this->set('pager_numbers', $pager_numbers); } public function find() { $datas=$this->Mac554FoodData->find('all'); $this->set('datas',$datas); //検索条件設定 $this->Prg->commonProcess(); //検索条件取得 $tabe=$this->passedArgs; $conditions = $this->Mac554FoodData->parseCriteria['$tabe']; //ページャ関係 $this->paginate =array( 'conditions' => $conditions, 'limit' =>10 ); $this->set('Mac554FoodDatas',$this->paginate('Mac554FoodData')); // レイアウト関係 $this->layout = "plain"; $this->set("header_for_layout", "Sample Application"); $this->set("footer_for_layout", "copyright by SYODA-Tuyano. 2011."); // post時の処理 //$this->set('Mac554FoodDatas',$this->Mac554FoodData->find('all')); } public function index() { $this->layout = "plain"; $this->set("header_for_layout", "Sample Application"); $this->set("footer_for_layout", "copyright by SYODA-Tuyano. 2011."); //レイアウト } } ?> で、検索フォームはエレメントで <?php echo $this->Form->create('Mac554FoodData', array('url' => '/Mac554FoodDatas/find'))?> <fieldset> <legend>Search or Die!</legend> <dl> <dt><label>ユーザname</label></dt> <dd><?php echo $this->Form->input('name', array( 'type' => 'text', 'div' => false, 'label' => false))?></dd> <dt><label>time</label></dt> <dd><?php echo $this->Form->input('time', array( 'type' => 'text', 'div' => false, 'label' => false ))?></dd> <dt><label>naiyoudao</label></dt> <dd><?php echo $this->Form->input('naiyoudao', array( 'type' => 'text', 'div' => false, 'label' => false ))?></dd> </dl> <?php echo $this->Form->submit('検索',array('div'=>false,'escape'=>false))?> </fieldset> <?php echo $this->Form->end()?> のように作りました。 モデルは、 <?php class Mac554FoodDatas extends AppModel{ public $name=Mac554FoodData public $actsAs = array('Search.Searchable'); // 検索対象のフィルタ設定 public $filterArgs = array( array('name' => 'name', 'type' => 'value', 'field' => 'Mac554FoodData.name'), array('name' => 'time', 'type' => 'like', 'field' => 'Mac554FoodData.time'), array('name' => 'naiyoudao', 'type' => 'like', 'field' => 'Mac554FoodData.naiyoudao'), ); //検索対象のフィールド設定 public $presetVars = array( array('field' => 'name', 'type' => 'value'), array('field' => 'time', 'type' => 'value'), array('field' => 'naiyoudao', 'type' => 'value'), ); } という感じで作りました。 投げているSQL文を見ると、 SELECT `Mac554FoodData`.`id`, `Mac554FoodData`.`time`, `Mac554FoodData`.`name`, `Mac554FoodData`.`naiyoudao`, `Mac554FoodData`.`twinoid` FROM `mac554_foodlog`.`mac554_food_datas` AS `Mac554FoodData` WHERE 1 = 1 となっています。 よろしくお願い致します

    • ベストアンサー
    • PHP
  • vb.net トランザクション処理について

    VB2005、SQLServer2005環境です。 VB.Netのトランザクション処理でエラーが発生します。 エラー内容の意味すらわかりません。 どなたかご教授お願いします。 *エラー内容 "System.InvalidOperationException: ExecuteReader は、コマンドに割り当てられた接続が保留状態である ローカルのトランザクションにあるとき、トランザクション オブジェクトを持つコマンドが必要です。 コマンドの Transaction プロパティがまだ初期化されていません。 Private Sub BTN_更新_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BTN_更新.Click Dim strsql As String Dim Tran As SqlClient.SqlTransaction = Nothing '---DB接続 Call DBConnect() Try '---SQL文作成 strsql = "SELECT * FROM Aテーブル" '---SQL文を作成して実行する Dim comm As SqlCommand = New SqlCommand(strsql, Con) '---データアダプタの作成 Dim dataadapter As SqlDataAdapter = New SqlDataAdapter(comm) '---データセットへの読み込み Dim ds As DataSet = New DataSet() dataadapter.Fill(ds, "Aテーブル") Dim dt As New DataTable dt = ds.Tables("Aテーブル") '---主キーの設定 dt.PrimaryKey = New DataColumn() {dt.Columns("Aテーブル")} '---データの更新 Dim targetRow As DataRow targetRow = dt.NewRow() targetRow = dt.Rows.Find(TXT_コード.Text) targetRow("コード") = TXT_コード.Text targetRow("氏名") = TXT_氏名.Text '---コマンド自動作成 Dim cb As SqlCommandBuilder = New SqlCommandBuilder(dataadapter) '---トランザクション開始 Tran = Con.BeginTransaction() '---データベースの更新 dataadapter.Update(ds, "社員テーブル")     <<<エラーになります。 '---トランザクション完了 Tran.Commit() Catch oExcept As Exception '---ロールバック Tran.Rollback() '例外が発生した時の処理 MessageBox.Show(oExcept.ToString, "例外発生") Finally '---DB切断 Call Disconnect() End Try

  • CakePHPでテーブルからデータを選択したデータを受け渡し、次ページで表示する動作について

    現在CakePHPを使用して研修用の受講登録ページを作成しています。 やりたい事としては、 (1)ページ1でデータベースに入っているコース一覧をテーブルに表示 (2)ページ1で各行にチェックボックスがついており、選択したコースのIDを次ページに受け渡しする。 (3)ページ2で受け取ったデータ(コースのID)を元にFindで検索、テーブルに表示する。 といった感じです。 現在(2)まではできているのですが、(3)の部分でうまくいかずに困っています。 現在の状態は、(2)の部分ではチェックボックスの名前をコースのIDと同じ数字にし選択したチェックの数値と、何件選択したかをカウントしたものを変数に入れてFormにて受け渡しています。 そして、(3)で受け取ったデータを元にFindをかけたいのですが、Findの部分でどういった記述をすればいいのかわからず1週間ほど困っています。 グーグルでFindについて検索をしてみたものの、有効な答えを得られなかったので質問させて頂きます。よろしくお願いします。 なお、現在Findの部分は $conditions = array(  'conditions' => array(   'or' => array( for ($a=0;$a < $kensuu;$a++){ $data = $this->params['form'][$a]; if ($data == 1){ $check = 1; $count++; } if ($check == 1){ $sdata .= array('courceID' => '$a'); $a++; $data = $this->params['form'][$a]; if ($a == $kensuu){ $sdata .= array('courceID' => '$a'); $count++; } $a--; } $check = 0; } //$conditions = $conditions . $sdata; //$conditions .= ",),),);"; $sentakudata = $this->Pobs->find('all', $conditions); $this->set('sentakudata', $sentakudata); と、途中で止まっています。 選択したデータを $conditions = array(  'conditions' => array(   'or' => array( array('courceID' => '○○'), array('courceID' => '○○'), と、いった感じで自動で条件の部分に追加していきたいのです。

    • 締切済み
    • PHP
  • CakePHPでのコメント数表示について

    CakePHPを使って簡単な掲示板を開発しているのですが、トップページに 各トピックについたコメント数を表示させる方法で壁にぶち当たってしまっております。 データの取り出し方及び表示方法について教えて頂ければと思います。 DB構造(モデル)としては、 ==================================== ■掲示板(post.php) テーブル:posts id title contents ■コメント(comment.php) テーブル:comments id post_id comment ==================================== となっており、postsにhasMany、commentsにbelongsToで アソシエーションを貼ってあります。 コントローラー(posts_controller.php)では、 ==================================== $data = $this->Post->find('all',array('order' => array('Post.id' => 'desc'))); $this->set('data',$data); ==================================== という処理を行い、 ビュー(/posts/index.ctp)では、 ==================================== foreach($data as $val){ echo "<tr>"; echo "<td><a href='{$val['Post']['id']}'>$val['Post']['title']</a></td>"; echo "</tr>"; } ==================================== としています。 これで、トップページに行くと掲示板トピックスのタイトルの 一覧は表示できるのですが、その横についたコメント数を表示 させたいのです。 例)掲示板のタイトルです(13) 上記のように(○)とさせたいのです。 コントローラーの所でallではなくcountにすることで件数を取りだす ことができる所まではできるのですが、 $cnt = $this->Post->find('count',array('order' => array('Post.id' => 'desc'))); などとやっても本来取り出したいcommentsではなくpostsの件数を取りだす ことになってしまっています。 また、hasManyを利用すると、 Array( [0] => Array( [post] => Array( [id] => 1 [title] => 掲示板のタイトルです [contents] => 掲示板の内容です [comment] => Array( [0] => Array( [id] => 1 [post_id] => 1 [comment] => コメント1です。 [1] => Array( [id] => 2 [post_id] => 1 [comment] => コメント2です。 ・ ・ ・ となる為、ビューでの表示のさせ方にも困っております。

    • ベストアンサー
    • PHP
  • 注文内容で後処理を変えたい

    やりたいことは、フォームから注文した商品を一回の注文内容で後処理を変えたいということです。 具体的に話ますと POST送信された注文の中身がすべてが0の時、Aの処理 POST送信された注文の中身がすべて1の時、Bの処理 POST送信された注文の中身が1または0の時、Bの処理 POST送信された注文の中身が1または3の時、Bの処理 POST送信された注文の中身が1の商品または0の商品または3の時、Bの処理 POST送信された注文の中身がすべて2の時、Cの処理 POST送信された注文の中身に2が含まれる時、Cの処理 POST送信された注文の中身がすべて3の時、Dの処理 POST送信された注文の中身が3または0の時、Dの処理 つまり、下記のようなイメージで処理したいのです。 (例は7品目の注文があったとして考えていますが、何品目になるかは注文によってかわります。) 例 注文商品を処理したいイメージ ┃A │B │B │B │B │C │C │D │D ┃ ┠─┼─┼─┼─┼─┼─┼─┼─┼─┨ ┃0│1│1│1│1│2│2│3│3┃ ┃0│1│1│3│0│2│2│3│0┃ ┃0│1│0│1│3│2│3│3│0┃ ┃0│1│1│1│3│2│1│3│3┃ ┃0│1│0│3│0│2│0│3│3┃ ┃0│1│0│1│1│2│2│3│0┃ ┃0│1│1│1│3│2│3│3│0┃ そこで、一番簡単そうな「処理A」のような商品の注文について考えてみました。 そのプログラムが下記のプログラムですが、結果は「syori ERROR」と表示されます。 どうやら、正規表現マッチの記述が間違っているようなのですが、どう記述すればわかりません。 教えていただけないでしょうか。 また、他のパターンの場合の正規表現マッチの記述または処理の仕方も教えていただけないでしょうか。 phpのバージョンは4.4.2です。 $tyumonA = array(0,0,0,0,0,0,0); $tyumonB = array(1,1,1,1,1,1,1); $tyumonC = array(1,1,0,1,0,0,1); $tyumonD = array(1,3,1,1,3,1,1); $tyumonE = array(1,0,3,3,0,1,3); $tyumonF = array(2,2,2,2,2,2,2); $tyumonG = array(2,2,3,1,0,2,3); $tyumonH = array(3,3,3,3,3,3,3); $tyumonI = array(3,0,0,3,3,0,0); foreach($tyumonA as $data){ $num = count($data); $deff =0; for($i=0; $i<$num; $i++){ if(preg_match('/0[$i]/', $data[$i])){ echo '<p>' . 'OK!' . '</p>'; $deff++; }else{ echo '<p>' . 'ERROR' . '</p>'; } } } if($deff == $num){ echo 'syori_A'; }else{ echo 'syori ERROR'; } 最終的にはこんな形にしたいです。 foreach($tyumon as $data){ if(){ $result = syori_A; }elseif(){ $result = syori_B; }elseif(){ $result = syori_B; }elseif(){ $result = syori_B; }elseif(){ $result = syori_B; }elseif(){ $result = syori_C; }elseif(){ $result = syori_C; }elseif(){ $result = syori_D; }elseif(){ $result = syori_D; }else{ continue; } } よろしくお願いします。

    • ベストアンサー
    • PHP
  • PHP+MySQLでrollback出来ない

    PHP5 + MySQL5環境です。 以下のようなソースでロールバックさせたいのですが、 実行後、「phpMyAdmin」というDB操作ツールで対象テーブルを見てみると データが登録されてしまっています。(ロールバック出来ていない!?) どなたか原因がお解りでしたらご教授の程宜しくお願い致します。m(_ _)m ※ソースが見難いので、画像で見やすいものを添付します。 ※尚、catch句のデバッグは「bool(true) ロールバック実行」と返ってきます。 //***メイン処理ソース***************************** $sObj = new SQL_Controller(); $res = $sObj->tran_start(); if(!$res) exit; try{ //DB登録------------------ $res1 = $sObj->Customer_mst_Insert($_SESSION['CustomerInfo']); if(!$res1) throw new Exception("Customer_mst_Insert error"); throw new Exception("★rollbackテストの為、ここでワザとthrowしてみる★"); //コミット------------------ $sObj->tran_commit(); } catch(Exception $e) { //異常時はロールバックする-- $res = $sObj->tran_rollback(); var_dump($res); echo "ロールバック実行"; } //***↑メイン処理終わり。以下クラス。***************************** class SQL_Controller extends MySQL{ } class MySQL{ function query($sql){ //クエリ実行 return mysql_query($sql); } function tran_start(){ //■トランザクション開始------ try{ $res = $this->query("set autocommit = 0"); if(!$res) throw new Exception(); $res = $this->query("begin"); if(!$res) throw new Exception(); } catch(Exception $e) { return false; } return true; } function tran_commit(){ //■コミット------ return $this->query("commit"); } function tran_rollback(){ //■ロールバック------ return $this->query("rollback"); } }

    • ベストアンサー
    • PHP

専門家に質問してみよう