The nested transaction example here is great, but it's missing a key piece of the puzzle. Commits will commit everything, I only wanted commits to actually commit when the outermost commit has been completed. This can be done in InnoDB with savepoints.
<?php
class Database extends PDO
{
protected $transactionCount = 0;
public function beginTransaction()
{
if (!$this->transactionCounter++) {
return parent::beginTransaction();
}
$this->exec('SAVEPOINT trans'.$this->transactionCounter);
return $this->transactionCounter >= 0;
}
public function commit()
{
if (!--$this->transactionCounter) {
return parent::commit();
}
return $this->transactionCounter >= 0;
}
public function rollback()
{
if (--$this->transactionCounter) {
$this->exec('ROLLBACK TO trans'.$this->transactionCounter + 1);
return true;
}
return parent::rollback();
}
}