Yii2 で DB トランザクションを使用する単純なコードがあります。これにより、ユーザーの残高が更新され、ユーザーの残高履歴に新しいレコードが追加されます。
//User model
public function changeBalance(UserBalanceHistory $balance)
{
$balance->balance = $this->balance;
$balance->user_id = $this->id;
$this->balance = $this->getBalance() + $balance->getDelta();
$transaction = Yii::$app->db->beginTransaction();
try {
if ($balance->save() && $this->save()) {
$transaction->commit();
return true;
}
} catch (Exception $e) {
Yii::error($e->getMessage());
}
$transaction->rollBack();
}
データの整合性を保つために、DB トランザクションを頻繁に使用する必要があります。しかし、上記のような DB トランザクションを処理するには多くのコード行が必要になるため、コードを動員する次の関数を作成しました。
function dbTransaction(callable $callback)
{
$transaction = Yii::$app->db->beginTransaction();
try {
//if callback returns true than commit transaction
if (call_user_func($callback)) {
$transaction->commit();
Yii::trace('Transaction wrapper success');
}
} catch (\Exception $e) {
$transaction->rollBack();
throw $e;
}
$transaction->rollBack();
}
この関数を使用すると、次のようなトランザクションを処理できます。
//User model
public function changeBalance(UserBalanceHistory $balance)
{
dbTransaction(
function () use ($balance) {
$balance->balance = $this->balance;
$balance->user_id = $this->id;
$this->balance = $this->getBalance() + $balance->getDelta();
return $balance->save() && $this->save();
}
);
}
ご覧のとおり、2 番目の方法はトランザクションを非常に快適に使用できます。しかし、この時点で、dbTransaction
関数が正しく機能するかどうかわかりませんか? コードのレビューと、潜在的な問題を指摘するメモを歓迎します。ありがとう