Skip to content

Commit

Permalink
Ignore the createOrFirst savepoint to run callbacks
Browse files Browse the repository at this point in the history
  • Loading branch information
tonysm committed Sep 20, 2023
1 parent d9538d6 commit e6de881
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 11 deletions.
12 changes: 12 additions & 0 deletions src/Illuminate/Database/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -1545,6 +1545,18 @@ public function unsetTransactionManager()
$this->transactionsManager = null;
}

/**
* Ignores the current transaction level when calling the callbacks.
*
* @return void
*/
public function ignoreLatestTransactionForCallbacks()
{
$this->transactionsManager?->callbacksShouldIgnore(
$this->transactionsManager?->getTransactions()?->last()
);
}

/**
* Determine if the connection is in a "dry run".
*
Expand Down
11 changes: 6 additions & 5 deletions src/Illuminate/Database/DatabaseTransactionsManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class DatabaseTransactionsManager
/**
* The database transaction that should be ignored by callbacks.
*
* @var \Illuminate\Database\DatabaseTransactionRecord
* @var \Illuminate\Support\Collection
*/
protected $callbacksShouldIgnore;

Expand All @@ -26,6 +26,7 @@ class DatabaseTransactionsManager
public function __construct()
{
$this->transactions = collect();
$this->callbacksShouldIgnore = collect();
}

/**
Expand Down Expand Up @@ -56,7 +57,7 @@ public function rollback($connection, $level)
)->values();

if ($this->transactions->isEmpty()) {
$this->callbacksShouldIgnore = null;
$this->callbacksShouldIgnore = collect();
}
}

Expand All @@ -77,7 +78,7 @@ public function commit($connection)
$forThisConnection->map->executeCallbacks();

if ($this->transactions->isEmpty()) {
$this->callbacksShouldIgnore = null;
$this->callbacksShouldIgnore = collect();
}
}

Expand All @@ -104,7 +105,7 @@ public function addCallback($callback)
*/
public function callbacksShouldIgnore(DatabaseTransactionRecord $transaction)
{
$this->callbacksShouldIgnore = $transaction;
$this->callbacksShouldIgnore->push($transaction);

return $this;
}
Expand All @@ -117,7 +118,7 @@ public function callbacksShouldIgnore(DatabaseTransactionRecord $transaction)
public function callbackApplicableTransactions()
{
return $this->transactions->reject(function ($transaction) {
return $transaction === $this->callbacksShouldIgnore;
return $this->callbacksShouldIgnore->contains($transaction);
})->values();
}

Expand Down
14 changes: 11 additions & 3 deletions src/Illuminate/Database/Eloquent/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -1721,9 +1721,17 @@ public function withCasts($casts)
*/
public function withSavepointIfNeeded(Closure $scope): mixed
{
return $this->getQuery()->getConnection()->transactionLevel() > 0
? $this->getQuery()->getConnection()->transaction($scope)
: $scope();
$connection = $this->getQuery()->getConnection();

if ($connection->transactionLevel() === 0) {
return $scope();
}

return $connection->transaction(function () use ($connection, $scope) {
$connection->ignoreLatestTransactionForCallbacks();

return $scope();
});
}

/**
Expand Down
4 changes: 1 addition & 3 deletions src/Illuminate/Foundation/Testing/RefreshDatabase.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,7 @@ public function beginDatabaseTransaction()
$connection->setEventDispatcher($dispatcher);

if ($this->app->resolved('db.transactions')) {
$this->app->make('db.transactions')->callbacksShouldIgnore(
$this->app->make('db.transactions')->getTransactions()->first()
);
$connection->ignoreLatestTransactionForCallbacks();
}
}

Expand Down

0 comments on commit e6de881

Please sign in to comment.