title: Db Transactions in Yii2 with callbacks
body: <p>I have simple code which uses DB transaction in Yii2, this updates user balance and adds a new record to user balance history. </p>
  
  <pre><code>//User model
  public function changeBalance(UserBalanceHistory $balance)
  {
      $balance-&gt;balance = $this-&gt;balance;
      $balance-&gt;user_id = $this-&gt;id;
      $this-&gt;balance    = $this-&gt;getBalance() + $balance-&gt;getDelta();
  
      $transaction = Yii::$app-&gt;db-&gt;beginTransaction();
      try {
          if ($balance-&gt;save() &amp;&amp; $this-&gt;save()) {
              $transaction-&gt;commit();
              return true;
          }
      } catch (Exception $e) {
          Yii::error($e-&gt;getMessage());
      }
  
      $transaction-&gt;rollBack();
  }
  </code></pre>
  
  <p>I should use DB transactions frequently to save data integrity. But handling DB transactions like above requires a lot of code lines, so I created the following function which mobilizes my codes:</p>
  
  <pre><code>function dbTransaction(callable $callback)
  {
      $transaction = Yii::$app-&gt;db-&gt;beginTransaction();
  
      try {
          //if callback returns true than commit transaction
          if (call_user_func($callback)) {
              $transaction-&gt;commit();
              Yii::trace('Transaction wrapper success');
          }
      } catch (\Exception $e) {
          $transaction-&gt;rollBack();
          throw $e;
      }
      $transaction-&gt;rollBack();
  }
  </code></pre>
  
  <p>With this function I can handle transactions like this:</p>
  
  <pre><code>//User model
  public function changeBalance(UserBalanceHistory $balance)
  {
      dbTransaction(
          function () use ($balance) {
              $balance-&gt;balance = $this-&gt;balance;
              $balance-&gt;user_id = $this-&gt;id;
              $this-&gt;balance    = $this-&gt;getBalance() + $balance-&gt;getDelta();
  
              return $balance-&gt;save() &amp;&amp; $this-&gt;save();
          }
      );
  }
  </code></pre>
  
  <p>As you see the second way is very comfortable using transactions. But on this point, I am not sure that <code>dbTransaction</code> function works correctly or nor? Code review and notes which points potential issues are appreciated. Thanks</p>