Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions docs/en/appendices/5-4-migration-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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.
Expand Down
26 changes: 26 additions & 0 deletions docs/en/orm/database-basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
29 changes: 9 additions & 20 deletions docs/en/orm/table-objects.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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

Expand Down
Loading