豆豆友情提示:这是一个非官方 GitHub 代理镜像,主要用于网络测试或访问加速。请勿在此进行登录、注册或处理任何敏感信息。进行这些操作请务必访问官方网站 github.com。 Raw 内容也通过此代理提供。
Skip to content

Commit 3adcb23

Browse files
Merge pull request #8281 from cakephp/docs/connection-after-commit
Document Connection::afterCommit() and deferred commit events
2 parents 5b47f4f + e86bd9d commit 3adcb23

File tree

3 files changed

+78
-4
lines changed

3 files changed

+78
-4
lines changed

docs/en/appendices/5-4-migration-guide.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ version is reported as `unknown`), the header is omitted.
4545
has changed from `select` to `subquery`. If you need the previous behavior,
4646
explicitly set `'strategy' => 'select'` when defining associations.
4747
See [Associations](../orm/associations#has-many-associations) for more details.
48+
- `Model.afterSaveCommit` and `Model.afterDeleteCommit` events are now fired
49+
when `save()` or `delete()` is called inside an outer transaction. Previously,
50+
these events were silently suppressed. They are now deferred until the
51+
outermost transaction commits, and discarded on rollback.
52+
See [Table Objects](../orm/table-objects#aftersavecommit) for more details.
4853

4954
### Controller
5055

@@ -99,6 +104,9 @@ version is reported as `unknown`), the header is omitted.
99104
See [Query Builder](../orm/query-builder#advanced-conditions).
100105
- Added `inOrNull()` and `notInOrNull()` methods for combining `IN` conditions with `IS NULL`.
101106
- Added `isDistinctFrom()` and `isNotDistinctFrom()` methods for null-safe comparisons.
107+
- Added `Connection::afterCommit()` to register callbacks that run after the
108+
outermost transaction commits. Callbacks are discarded on rollback.
109+
See [Database Basics](../orm/database-basics#aftercommit) for more details.
102110
- Added `except()` and `exceptAll()` methods on `SelectQuery` for `EXCEPT`
103111
and `EXCEPT ALL` set operations. `EXCEPT ALL` is supported on PostgreSQL
104112
and recent MySQL/MariaDB versions; it is not supported on SQLite or SQL Server.

docs/en/orm/database-basics.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,6 +1107,53 @@ do the following:
11071107
- If the closure returns `false`, a rollback will be issued.
11081108
- If the closure executes successfully, the transaction will be committed.
11091109

1110+
### afterCommit
1111+
1112+
`method` Cake\\Database\\Connection::**afterCommit**(callable $callback): void
1113+
1114+
You can register callbacks to run after the outermost transaction commits using
1115+
``afterCommit()``. This is useful for deferring side effects like sending
1116+
emails, dispatching jobs, or invalidating caches until you know the data has
1117+
been persisted:
1118+
1119+
```php
1120+
$connection->begin();
1121+
$connection->execute('UPDATE articles SET published = ? WHERE id = ?', [true, 2]);
1122+
$connection->afterCommit(function () {
1123+
// Send notification email — only runs if the transaction commits.
1124+
$this->mailer->send('article-published');
1125+
});
1126+
$connection->commit(); // Callback fires here.
1127+
```
1128+
1129+
Callbacks are discarded if the transaction is rolled back. When nested
1130+
transactions are in use, callbacks registered at any depth are deferred until
1131+
the outermost transaction commits:
1132+
1133+
```php
1134+
$connection->begin();
1135+
$connection->afterCommit(function () {
1136+
// This fires after the outermost commit.
1137+
});
1138+
1139+
$connection->begin(); // Nested (savepoint)
1140+
$connection->afterCommit(function () {
1141+
// Also deferred to outermost commit.
1142+
});
1143+
$connection->commit(); // Releases savepoint — callbacks don't fire yet.
1144+
1145+
$connection->commit(); // Outermost commit — both callbacks fire now.
1146+
```
1147+
1148+
If ``afterCommit()`` is called when no transaction is active, the callback
1149+
executes immediately. This matches the semantics of the ORM's
1150+
``Model.afterSaveCommit`` event, which also fires immediately for non-atomic
1151+
saves.
1152+
1153+
::: info Added in version 5.4.0
1154+
`Connection::afterCommit()` was added.
1155+
:::
1156+
11101157
## Interacting with Statements
11111158

11121159
When using the lower level database API, you will often encounter statement

docs/en/orm/table-objects.md

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,18 @@ The `Model.afterSave` event is fired after an entity is saved.
320320
The `Model.afterSaveCommit` event is fired after the transaction in which the
321321
save operation is wrapped has been committed. It's also triggered for non atomic
322322
saves where database operations are implicitly committed. The event is triggered
323-
only for the primary table on which `save()` is directly called. The event is
324-
not triggered if a transaction is started before calling save.
323+
only for the primary table on which `save()` is directly called.
324+
325+
When `save()` is called inside an outer transaction (e.g. one started with
326+
`Connection::begin()`), the event is deferred until the outermost transaction
327+
commits. If the outer transaction is rolled back, the event is discarded. This
328+
ensures the event only fires after data has been persisted to the database.
329+
330+
::: info Changed in version 5.4.0
331+
Previously, this event was not triggered if a transaction was started before
332+
calling `save()`. It is now deferred and fires after the outermost
333+
transaction commits.
334+
:::
325335

326336
### beforeDelete
327337

@@ -342,10 +352,19 @@ The `Model.afterDelete` event is fired after an entity has been deleted.
342352
`method` Cake\\ORM\\Table::**afterDeleteCommit**(EventInterface $event, EntityInterface $entity, ArrayObject $options): void
343353

344354
The `Model.afterDeleteCommit` event is fired after the transaction in which the
345-
delete operation is wrapped has been is committed. It's also triggered for non
355+
delete operation is wrapped has been committed. It's also triggered for non
346356
atomic deletes where database operations are implicitly committed. The event is
347357
triggered only for the primary table on which `delete()` is directly called.
348-
The event is not triggered if a transaction is started before calling delete.
358+
359+
When `delete()` is called inside an outer transaction, the event is deferred
360+
until the outermost transaction commits. If the outer transaction is rolled
361+
back, the event is discarded.
362+
363+
::: info Changed in version 5.4.0
364+
Previously, this event was not triggered if a transaction was started before
365+
calling `delete()`. It is now deferred and fires after the outermost
366+
transaction commits.
367+
:::
349368

350369
### Stopping Table Events
351370

0 commit comments

Comments
 (0)