7

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関数が正しく機能するかどうかわかりませんか? コードのレビューと、潜在的な問題を指摘するメモを歓迎します。ありがとう

4

1 に答える 1

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();
 }
于 2017-11-09T10:15:51.857 に答える