2015-10-09 58 views
2

我有一個簡單的代碼,它在Yii2中使用db交易,這會更新用戶餘額併爲用戶餘額歷史添加新記錄。Db在回調中的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(); 
} 

我應該使用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(); 
     } 
    ); 
} 

正如你看到的第二種方式使用交易非常舒服。但在這一點上,我不確定dbTransaction函數可以正常工作嗎?代碼審查和指出潛在問題的意見是值得讚賞的。由於

+0

應該被移動到http://codereview.stackexchange.com/ – robsch

回答

0

最後一行之前刪除你的代碼$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(); 
}