<?php
namespace RedBeanPHP\Util;
use RedBeanPHP\OODB as OODB;
use RedBeanPHP\OODBBean as OODBBean;
use RedBeanPHP\RedException as RedException;
use RedBeanPHP\Adapter as Adapter;
/**
* Transaction Helper
*
* This code was originally part of the facade, however it has
* been decided to remove unique features to service classes like
* this to make them available to developers not using the facade class.
*
* Database transaction helper. This is a convenience class
* to perform a callback in a database transaction. This class
* contains a method to wrap your callback in a transaction.
*
* @file RedBeanPHP/Util/Transaction.php
* @author Gabor de Mooij and the RedBeanPHP Community
* @license BSD/GPLv2
*
* @copyright
* copyright (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community
* This source file is subject to the BSD/GPLv2 License that is bundled
* with this source code in the file license.txt.
*/
class Transaction
{
/**
* Wraps a transaction around a closure or string callback.
* If an Exception is thrown inside, the operation is automatically rolled back.
* If no Exception happens, it commits automatically.
* It also supports (simulated) nested transactions (that is useful when
* you have many methods that needs transactions but are unaware of
* each other).
*
* Example:
*
* <code>
* $from = 1;
* $to = 2;
* $amount = 300;
*
* R::transaction(function() use($from, $to, $amount)
* {
* $accountFrom = R::load('account', $from);
* $accountTo = R::load('account', $to);
* $accountFrom->money -= $amount;
* $accountTo->money += $amount;
* R::store($accountFrom);
* R::store($accountTo);
* });
* </code>
*
* @param Adapter $adapter Database Adapter providing transaction mechanisms.
* @param callable $callback Closure (or other callable) with the transaction logic
*
* @return mixed
*/
public static function transaction( Adapter $adapter, $callback )
{
if ( !is_callable( $callback ) ) {
throw new RedException( 'R::transaction needs a valid callback.' );
}
static $depth = 0;
$result = null;
try {
if ( $depth == 0 ) {
$adapter->startTransaction();
}
$depth++;
$result = call_user_func( $callback ); //maintain 5.2 compatibility
$depth--;
if ( $depth == 0 ) {
$adapter->commit();
}
} catch ( \Exception $exception ) {
$depth--;
if ( $depth == 0 ) {
$adapter->rollback();
}
throw $exception;
}
return $result;
}
}
|