Skip to content

Instantly share code, notes, and snippets.

@alexmnv
Created May 24, 2019 08:34
Show Gist options
  • Save alexmnv/7c5595c44023dc67cbde2a005c413250 to your computer and use it in GitHub Desktop.
Save alexmnv/7c5595c44023dc67cbde2a005c413250 to your computer and use it in GitHub Desktop.
<?php
use Illuminate\Database\PostgresConnection as Connection;
class DBTransaction
{
/**
* Выполнение функкции в транзакции с возможностью указывать точки сохранения.
* - Если функция выполнится без ошибки (Exception), произойдёт полный коммит
* - Если функция выбросит исключение, то произойдёт коммит от начала до последнего вызовы `savepoint()`
*/
public static function run(Connection $connection, Callable $fn)
{
$startLevel = $connection->transactionLevel();
$connection->beginTransaction();
$transaction = new self($connection);
try {
return $fn($transaction);
}
catch(\Exception $e) {
$connection->rollBack($startLevel + $transaction->savepoints);
throw $e;
}
finally {
$endLevel = $connection->transactionLevel();
for ($n = $startLevel; $n <= $endLevel; $n++) {
$connection->commit();
}
}
}
/** @var Connection */
protected $connection;
protected $savepoints = 0;
protected function __construct(Connection $connection)
{
$this->connection = $connection;
}
public function savepoint()
{
$this->savepoints++;
$this->connection->beginTransaction();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment