БД транзакций в 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();
 }
Другие вопросы по тегам