БД транзакций в Yii2 с обратными вызовами
У меня есть простой код, который использует транзакции БД в Yii2, это обновляет баланс пользователя и добавляет новую запись в историю баланса пользователей.
//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();
}
Я должен часто использовать транзакции БД для сохранения целостности данных. Но обработка транзакций БД, как описано выше, требует много строк кода, поэтому я создал следующую функцию, которая мобилизует мои коды:
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();
}
);
}
Как видите, второй способ очень удобен при использовании транзакций. Но в этом вопросе я не уверен, что dbTransaction
функция работает правильно или нет? Обзор кода и заметки, которые указывают на потенциальные проблемы приветствуются. Спасибо
1 ответ
Удали свой код $transaction->rollBack();
до последней строки, потому что этот код всегда откат и отмена вашей транзакции
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();
}