Yii2中带有回调的DB事务

com*_*lex 6 transactions yii2 yii2-model

我有一个简单的代码,该代码在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();
}
Run Code Online (Sandbox Code Playgroud)

我应该经常使用数据库事务来保存数据完整性。但是像上面那样处理数据库事务需要很多代码行,因此我创建了以下函数来调动我的代码:

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();
}
Run Code Online (Sandbox Code Playgroud)

使用此功能,我可以处理如下交易:

//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();
        }
    );
}
Run Code Online (Sandbox Code Playgroud)

如您所见,第二种方法非常适合使用事务。但是,在这一点上,我不确定该dbTransaction功能是否正常运行?代码审查和注释指出了潜在的问题,我们对此表示赞赏。谢谢

jac*_*ack 6

$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();
 }
Run Code Online (Sandbox Code Playgroud)