@@ -358,6 +358,20 @@ abstract class BaseConnection implements ConnectionInterface
358358 */
359359 protected bool $ transException = false ;
360360
361+ /**
362+ * Callbacks to run after the outermost transaction commits.
363+ *
364+ * @var list<callable(): void>
365+ */
366+ protected array $ transCommitCallbacks = [];
367+
368+ /**
369+ * Callbacks to run after the outermost transaction rolls back.
370+ *
371+ * @var list<callable(): void>
372+ */
373+ protected array $ transRollbackCallbacks = [];
374+
361375 /**
362376 * Array of table aliases.
363377 *
@@ -985,13 +999,15 @@ public function transComplete(): bool
985999
9861000 // The query() function will set this flag to FALSE in the event that a query failed
9871001 if ($ this ->transStatus === false || $ this ->transFailure === true ) {
988- $ this ->transRollback ();
989-
990- // If we are NOT running in strict mode, we will reset
991- // the _trans_status flag so that subsequent groups of
992- // transactions will be permitted.
993- if ($ this ->transStrict === false ) {
994- $ this ->transStatus = true ;
1002+ try {
1003+ $ this ->transRollback ();
1004+ } finally {
1005+ // If we are NOT running in strict mode, we will reset
1006+ // the _trans_status flag so that subsequent groups of
1007+ // transactions will be permitted.
1008+ if ($ this ->transStrict === false ) {
1009+ $ this ->transStatus = true ;
1010+ }
9951011 }
9961012
9971013 return false ;
@@ -1008,6 +1024,48 @@ public function transStatus(): bool
10081024 return $ this ->transStatus ;
10091025 }
10101026
1027+ /**
1028+ * Register a callback to run after the outermost transaction commits.
1029+ *
1030+ * If no transaction is active, the callback runs immediately.
1031+ *
1032+ * @param callable(): void $callback
1033+ *
1034+ * @return $this
1035+ */
1036+ public function afterCommit (callable $ callback ): static
1037+ {
1038+ if ($ this ->transDepth === 0 ) {
1039+ $ callback ();
1040+
1041+ return $ this ;
1042+ }
1043+
1044+ $ this ->transCommitCallbacks [] = $ callback ;
1045+
1046+ return $ this ;
1047+ }
1048+
1049+ /**
1050+ * Register a callback to run after the outermost transaction rolls back.
1051+ *
1052+ * If no transaction is active, the callback is not run.
1053+ *
1054+ * @param callable(): void $callback
1055+ *
1056+ * @return $this
1057+ */
1058+ public function afterRollback (callable $ callback ): static
1059+ {
1060+ if ($ this ->transDepth === 0 ) {
1061+ return $ this ;
1062+ }
1063+
1064+ $ this ->transRollbackCallbacks [] = $ callback ;
1065+
1066+ return $ this ;
1067+ }
1068+
10111069 /**
10121070 * Begin Transaction
10131071 */
@@ -1055,6 +1113,11 @@ public function transCommit(): bool
10551113 if ($ this ->transDepth > 1 || $ this ->_transCommit ()) {
10561114 $ this ->transDepth --;
10571115
1116+ if ($ this ->transDepth === 0 ) {
1117+ $ this ->transRollbackCallbacks = [];
1118+ $ this ->runTransCommitCallbacks ();
1119+ }
1120+
10581121 return true ;
10591122 }
10601123
@@ -1074,6 +1137,11 @@ public function transRollback(): bool
10741137 if ($ this ->transDepth > 1 || $ this ->_transRollback ()) {
10751138 $ this ->transDepth --;
10761139
1140+ if ($ this ->transDepth === 0 ) {
1141+ $ this ->transCommitCallbacks = [];
1142+ $ this ->runTransRollbackCallbacks ();
1143+ }
1144+
10771145 return true ;
10781146 }
10791147
@@ -1102,6 +1170,32 @@ public function handleTransStatus(): void
11021170 }
11031171 }
11041172
1173+ /**
1174+ * Run and clear callbacks registered for a successful transaction commit.
1175+ */
1176+ protected function runTransCommitCallbacks (): void
1177+ {
1178+ $ callbacks = $ this ->transCommitCallbacks ;
1179+ $ this ->transCommitCallbacks = [];
1180+
1181+ foreach ($ callbacks as $ callback ) {
1182+ $ callback ();
1183+ }
1184+ }
1185+
1186+ /**
1187+ * Run and clear callbacks registered for a transaction rollback.
1188+ */
1189+ protected function runTransRollbackCallbacks (): void
1190+ {
1191+ $ callbacks = $ this ->transRollbackCallbacks ;
1192+ $ this ->transRollbackCallbacks = [];
1193+
1194+ foreach ($ callbacks as $ callback ) {
1195+ $ callback ();
1196+ }
1197+ }
1198+
11051199 /**
11061200 * Begin Transaction
11071201 */
0 commit comments