diff --git a/docs/en/appendices/5-4-migration-guide.md b/docs/en/appendices/5-4-migration-guide.md index 0e331043f9..3b346a2649 100644 --- a/docs/en/appendices/5-4-migration-guide.md +++ b/docs/en/appendices/5-4-migration-guide.md @@ -70,11 +70,6 @@ events are now registered while each plugin is bootstrapped. has changed from `select` to `subquery`. If you need the previous behavior, explicitly set `'strategy' => 'select'` when defining associations. See [Associations](../orm/associations#has-many-associations) for more details. -- `Model.afterSaveCommit` and `Model.afterDeleteCommit` events are now fired - when `save()` or `delete()` is called inside an outer transaction. Previously, - these events were silently suppressed. They are now deferred until the - outermost transaction commits, and discarded on rollback. - See [Table Objects](../orm/table-objects#aftersavecommit) for more details. - Table methods `save()`, `delete()`, `patchEntity()`, `patchEntities()` and `loadInto()` will now throw an exception if the entity being passed down does not belong to the table instance. This will prevent accidental data corruption or deleted records. If you don't want this new behavior, @@ -171,6 +166,9 @@ events are now registered while each plugin is bootstrapped. - Added `Connection::afterCommit()` to register callbacks that run after the outermost transaction commits. Callbacks are discarded on rollback. See [Database Basics](../orm/database-basics#aftercommit) for more details. +- Added the `Connection.afterCommit` event, which is fired once after the + outermost transaction commits. + See [Database Basics](../orm/database-basics#connection-aftercommit-event). - Added `except()` and `exceptAll()` methods on `SelectQuery` for `EXCEPT` and `EXCEPT ALL` set operations. `EXCEPT ALL` is supported on PostgreSQL and recent MySQL/MariaDB versions; it is not supported on SQLite or SQL Server. diff --git a/docs/en/orm/database-basics.md b/docs/en/orm/database-basics.md index be81151ece..8de8a95962 100644 --- a/docs/en/orm/database-basics.md +++ b/docs/en/orm/database-basics.md @@ -1179,6 +1179,32 @@ saves. `Connection::afterCommit()` was added. ::: +### Connection.afterCommit Event + +The connection also dispatches a `Connection.afterCommit` event once the +outermost transaction has committed. Use it for listeners that should react to +every committed transaction, instead of registering a callback per transaction: + +```php +use Cake\Event\EventInterface; + +$connection->getEventManager()->on( + 'Connection.afterCommit', + function (EventInterface $event): void { + // Runs once per outermost commit. + $connection = $event->getSubject(); + }, +); +``` + +The event is fired after all callbacks registered with `afterCommit()` have +run, and its subject is the connection. It is not fired for nested commits or +when the transaction is rolled back. + +::: info Added in version 5.4.0 +The `Connection.afterCommit` event was added. +::: + ## Interacting with Statements When using the lower level database API, you will often encounter statement diff --git a/docs/en/orm/table-objects.md b/docs/en/orm/table-objects.md index 7d3c0fcc3d..1b2542dfaa 100644 --- a/docs/en/orm/table-objects.md +++ b/docs/en/orm/table-objects.md @@ -329,18 +329,12 @@ The `Model.afterSave` event is fired after an entity is saved. The `Model.afterSaveCommit` event is fired after the transaction in which the save operation is wrapped has been committed. It's also triggered for non atomic saves where database operations are implicitly committed. The event is triggered -only for the primary table on which `save()` is directly called. +only for the primary table on which `save()` is directly called. The event is +not triggered if a transaction is started before calling save. -When `save()` is called inside an outer transaction (e.g. one started with -`Connection::begin()`), the event is deferred until the outermost transaction -commits. If the outer transaction is rolled back, the event is discarded. This -ensures the event only fires after data has been persisted to the database. - -::: info Changed in version 5.4.0 -Previously, this event was not triggered if a transaction was started before -calling `save()`. It is now deferred and fires after the outermost -transaction commits. -::: +To react once such an outer transaction commits, use +[Connection::afterCommit()](../orm/database-basics#aftercommit) or the +[Connection.afterCommit event](../orm/database-basics#connection-aftercommit-event). ### beforeDelete @@ -364,16 +358,11 @@ The `Model.afterDeleteCommit` event is fired after the transaction in which the delete operation is wrapped has been committed. It's also triggered for non atomic deletes where database operations are implicitly committed. The event is triggered only for the primary table on which `delete()` is directly called. +The event is not triggered if a transaction is started before calling delete. -When `delete()` is called inside an outer transaction, the event is deferred -until the outermost transaction commits. If the outer transaction is rolled -back, the event is discarded. - -::: info Changed in version 5.4.0 -Previously, this event was not triggered if a transaction was started before -calling `delete()`. It is now deferred and fires after the outermost -transaction commits. -::: +To react once such an outer transaction commits, use +[Connection::afterCommit()](../orm/database-basics#aftercommit) or the +[Connection.afterCommit event](../orm/database-basics#connection-aftercommit-event). ### Stopping Table Events