cakePHP覚書#2

ちょっと複雑なデータ更新が必要になってきたので、トランザクションを調べることにした。

ひとつのテーブルで更新と追加が同時発生、他のテーブルでも同様という風に二つのテーブルにまたがる処理ですが

アソシエーションでは定義できないようなもの。

まずMySQLのテーブルがMyISAMだとロールバックしても効かないので使えない。InnoDBに変更が必要となる。

show table  status;

で現状の確認をする。MyISAMで作っている既存テーブルもInnoDBに変更可能。

変更するには、phpMyAdminであればテーブルの「操作」で「ストレージエンジン」を「InnoDB」に変更して実行押すだけ。

alter table 'xxxx'  engine=InooDB;

が実行された。もちろんコマンドラインから、これを打ってもOKです。

さてさて、begin()  commit()  rollback() をどこで定義しておくか。

必要なテーブルのモデルだけで定義しておいてもいいけど面倒ですね。思い切ってapp_modelに書いとけば全部のモデルで継承してくれますから、これでいいかな。

いつものように、cake以下は触らないお約束で、cake/libs/modelのなかのapp_model.phpをapp/models以下にコピーしておいて追加します。

function begin() {
	$dbs = & ConnectionManager::getDataSource($this->useDbConfig);
	$dbs->begin($this);
}

function commit() {
	$dbs = & ConnectionManager::getDataSource($this->useDbConfig);
	$dbs->commit($this);

}

function rollback() {
	$dbs = & ConnectionManager::getDataSource($this->useDbConfig);
	$dbs->rollback($this);

}

これで、モデルの関数になるのでモデル名->begin()とかで使えます。

2つのモデルを同時更新なら

	ModelA->begin();

	ModelB->begin();

	処理ほにゃらら

	なんか問題あったら

	ModelA->rollback();

	ModelB->rollback();

	エラー無く終了。

	ModelA->commit();

	ModelB->commit();

こんな具合かな。それとsavaAllを使うときの注意もあった。saveAllの外側でトランザクション開始していてもループの途中でコミットされちゃうみたいです。対策としてはパラメータを追加しておくこと。

ModelA->saveAll($datas ,array('atomic'=>false);

こんなおまじないが必須だ。

追記:どうもModelA ModelB両方にbegin() rollback() commit()を行わなくても、ModelAだけやっておけば、両方に効力があるという記述を発見。まだ未検証です。

追記:検証しました。

実行されたSQLも確認しましたが、どれかひとつのモデルでトランザクション操作しておけばOKです。



コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です