diff --git a/src/Dibi/Connection.php b/src/Dibi/Connection.php index acc55b6..1227ad1 100644 --- a/src/Dibi/Connection.php +++ b/src/Dibi/Connection.php @@ -402,6 +402,23 @@ class Connection implements IConnection } + /** + * @return mixed + */ + public function transaction(callable $callback) + { + $this->begin(); + try { + $res = $callback(); + } catch (\Throwable $e) { + $this->rollback(); + throw $e; + } + $this->commit(); + return $res; + } + + /** * Result set factory. */ diff --git a/src/Dibi/dibi.php b/src/Dibi/dibi.php index 275af62..d68e4d0 100644 --- a/src/Dibi/dibi.php +++ b/src/Dibi/dibi.php @@ -25,6 +25,7 @@ declare(strict_types=1); * @method static void begin(string $savepoint = null) * @method static void commit(string $savepoint = null) * @method static void rollback(string $savepoint = null) + * @method static mixed transaction(callable $callback) * @method static Dibi\Reflection\Database getDatabaseInfo() * @method static Dibi\Fluent command() * @method static Dibi\Fluent select(...$args) diff --git a/tests/dibi/Connection.transactions.phpt b/tests/dibi/Connection.transactions.phpt index 04cfaa3..0a7d5bf 100644 --- a/tests/dibi/Connection.transactions.phpt +++ b/tests/dibi/Connection.transactions.phpt @@ -48,3 +48,24 @@ $conn->query('INSERT INTO [products]', [ ]); $conn->commit(); Assert::same(4, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle()); + + + +Assert::exception(function () use ($conn) { + $conn->transaction(function () use ($conn) { + $conn->query('INSERT INTO [products]', [ + 'title' => 'Test product', + ]); + throw new Exception('my exception'); + }); +}, \Throwable::class, 'my exception'); + +Assert::same(4, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle()); + +$conn->transaction(function () use ($conn) { + $conn->query('INSERT INTO [products]', [ + 'title' => 'Test product', + ]); +}); + +Assert::same(5, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle());