class DatabaseTransactionsManager extends DatabaseTransactionsManager

Testing-aware transaction manager that properly handles RefreshDatabase's wrapper transaction.

When RefreshDatabase wraps tests in a transaction, this manager ensures that afterCommit callbacks execute at the appropriate time (when returning to the wrapper level) rather than waiting for level 0 which never happens during wrapped tests.

Properties

protected array<int, null|string> $connectionsTransacting

The names of the connections transacting during tests.

protected DatabaseTransactionRecord> $wrappingTransactions

The transaction records owned by the test wrappers.

Methods

getCommittedTransactionsInternal()

Get all committed transactions for the current coroutine.

getPendingTransactionsInternal()

Get all pending transactions for the current coroutine.

getCurrentTransactionForConnection(string $connection)

Get current transaction for a connection.

void
begin(string $connection, int $level)

Start a new database transaction.

commit(string $connection, int $levelBeingCommitted, int $newTransactionLevel)

Commit the root database transaction and execute callbacks.

void
stageTransactions(string $connection, int $levelBeingCommitted)

Move relevant pending transactions to a committed state.

void
rollback(string $connection, int $newTransactionLevel)

Rollback the active database transaction.

void
removeAllTransactionsForConnection(string $connection)

Remove all pending, completed, and current transactions for the given connection name.

removeCommittedTransactionsThatAreChildrenOf(DatabaseTransactionRecord $transaction)

Remove and return all committed descendants of the given transaction.

void
executeCommitCallbacks(Collection $transactions)

Execute commit callbacks for every detached transaction.

void
executeRollbackCallbacks(Collection $transactions)

Execute rollback callbacks for every detached transaction.

void
addCallback(callable $callback, string|null $connection = null)

Register a transaction callback.

void
addCallbackForRollback(callable $callback, string|null $connection = null)

Register a callback for transaction rollback.

bool
hasApplicableTransaction(string|null $connection = null)

Determine whether a callback would wait for an open transaction.

latestApplicableTransaction(string|null $connection)

Get the latest applicable transaction, optionally limited to a connection.

callbackApplicableTransactions()

Get the transactions that are applicable to callbacks.

bool
afterCommitCallbacksShouldBeExecuted(int $level)

Determine if after commit callbacks should be executed for the given transaction level.

getPendingTransactions()

Get all of the pending transactions.

getCommittedTransactions()

Get all of the committed transactions.

static bool
hasNonCoroutinePendingTransactions()

Check whether there are pending transactions in non-coroutine storage.

static void
copyToNonCoroutineState()

Copy transaction state from the current coroutine to non-coroutine storage.

static void
copyFromNonCoroutineState()

Restore the test lifecycle's transaction state in the current coroutine.

static void
clearNonCoroutineState()

Clear all transaction state from non-coroutine storage.

__construct(array $connectionsTransacting)

Create a new database transaction manager instance.

void
beginTransactions(DatabaseManager $database)

Begin the test wrappers and remember their transaction records.

Details

protected Collection getCommittedTransactionsInternal()

Get all committed transactions for the current coroutine.

Return Value

Collection

protected Collection getPendingTransactionsInternal()

Get all pending transactions for the current coroutine.

Return Value

Collection

protected DatabaseTransactionRecord|null getCurrentTransactionForConnection(string $connection)

Get current transaction for a connection.

Parameters

string $connection

Return Value

DatabaseTransactionRecord|null

void begin(string $connection, int $level)

Start a new database transaction.

Parameters

string $connection
int $level

Return Value

void

Collection commit(string $connection, int $levelBeingCommitted, int $newTransactionLevel)

Commit the root database transaction and execute callbacks.

Parameters

string $connection
int $levelBeingCommitted
int $newTransactionLevel

Return Value

Collection

void stageTransactions(string $connection, int $levelBeingCommitted)

Move relevant pending transactions to a committed state.

Parameters

string $connection
int $levelBeingCommitted

Return Value

void

void rollback(string $connection, int $newTransactionLevel)

Rollback the active database transaction.

Parameters

string $connection
int $newTransactionLevel

Return Value

void

protected void removeAllTransactionsForConnection(string $connection)

Remove all pending, completed, and current transactions for the given connection name.

Parameters

string $connection

Return Value

void

protected Collection removeCommittedTransactionsThatAreChildrenOf(DatabaseTransactionRecord $transaction)

Remove and return all committed descendants of the given transaction.

Parameters

DatabaseTransactionRecord $transaction

Return Value

Collection

protected void executeCommitCallbacks(Collection $transactions)

Execute commit callbacks for every detached transaction.

Parameters

Collection $transactions

Return Value

void

protected void executeRollbackCallbacks(Collection $transactions)

Execute rollback callbacks for every detached transaction.

Parameters

Collection $transactions

Return Value

void

void addCallback(callable $callback, string|null $connection = null)

Register a transaction callback.

A null connection selects the most recently started applicable transaction on any connection. The callback runs when that transaction and its enclosing stack on the same connection commit.

Parameters

callable $callback
string|null $connection

resolved owner name from Connection::getNameWithReadWriteType()

Return Value

void

void addCallbackForRollback(callable $callback, string|null $connection = null)

Register a callback for transaction rollback.

A null connection selects the most recently started applicable transaction on any connection. The callback runs when that transaction and its enclosing stack on the same connection roll back.

Parameters

callable $callback
string|null $connection

resolved owner name from Connection::getNameWithReadWriteType()

Return Value

void

bool hasApplicableTransaction(string|null $connection = null)

Determine whether a callback would wait for an open transaction.

Parameters

string|null $connection

Return Value

bool

protected DatabaseTransactionRecord|null latestApplicableTransaction(string|null $connection)

Get the latest applicable transaction, optionally limited to a connection.

Parameters

string|null $connection

Return Value

DatabaseTransactionRecord|null

at line 77
Collection callbackApplicableTransactions()

Get the transactions that are applicable to callbacks.

Only actual wrapper records are excluded: pooled child sessions can have level-one application transactions on the same connection name.

Return Value

Collection

at line 90
bool afterCommitCallbacksShouldBeExecuted(int $level)

Determine if after commit callbacks should be executed for the given transaction level.

Returns true at level 1 (the RefreshDatabase wrapper level) instead of level 0, since the wrapper transaction is never committed during tests.

Parameters

int $level

Return Value

bool

Collection getPendingTransactions()

Get all of the pending transactions.

Return Value

Collection

Collection getCommittedTransactions()

Get all of the committed transactions.

Return Value

Collection

static bool hasNonCoroutinePendingTransactions()

Check whether there are pending transactions in non-coroutine storage.

Return Value

bool

static void copyToNonCoroutineState()

Copy transaction state from the current coroutine to non-coroutine storage.

This copies coroutine-local transaction state into worker-global storage, so request-time use can leak or race across concurrent requests.

Return Value

void

static void copyFromNonCoroutineState()

Restore the test lifecycle's transaction state in the current coroutine.

This deliberately shares transaction ownership across setup, test and teardown; normal child coroutines must own separate transactions.

Return Value

void

static void clearNonCoroutineState()

Clear all transaction state from non-coroutine storage.

This mutates worker-global transaction state, so request-time use can race with concurrent requests using the same storage.

Return Value

void

at line 41
__construct(array $connectionsTransacting)

Create a new database transaction manager instance.

Parameters

array $connectionsTransacting

at line 49
void beginTransactions(DatabaseManager $database)

Begin the test wrappers and remember their transaction records.

Parameters

DatabaseManager $database

Return Value

void