File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -1066,6 +1066,52 @@ public function afterRollback(callable $callback): static
10661066 return $ this ;
10671067 }
10681068
1069+ /**
1070+ * Run the callback inside a transaction.
1071+ *
1072+ * @template TReturn
1073+ *
1074+ * @param callable(self): TReturn $callback
1075+ *
1076+ * @return false|TReturn
1077+ */
1078+ public function transaction (callable $ callback ): mixed
1079+ {
1080+ if (! $ this ->transEnabled ) {
1081+ return $ callback ($ this );
1082+ }
1083+
1084+ if (! $ this ->transBegin ()) {
1085+ return false ;
1086+ }
1087+
1088+ try {
1089+ $ result = $ callback ($ this );
1090+ } catch (Throwable $ e ) {
1091+ try {
1092+ $ this ->transRollback ();
1093+ } catch (Throwable $ rollbackException ) {
1094+ log_message ('error ' , 'Database: Transaction callback threw an exception before rollback failed: ' . $ e );
1095+
1096+ throw $ rollbackException ;
1097+ } finally {
1098+ if ($ this ->transDepth > 0 ) {
1099+ $ this ->transStatus = false ;
1100+ } elseif ($ this ->transStrict === false ) {
1101+ $ this ->transStatus = true ;
1102+ }
1103+ }
1104+
1105+ throw $ e ;
1106+ }
1107+
1108+ if (! $ this ->transComplete ()) {
1109+ return false ;
1110+ }
1111+
1112+ return $ result ;
1113+ }
1114+
10691115 /**
10701116 * Begin Transaction
10711117 */
Original file line number Diff line number Diff line change @@ -133,6 +133,17 @@ public function afterCommit(callable $callback): static;
133133 */
134134 public function afterRollback (callable $ callback ): static ;
135135
136+ /**
137+ * Run the callback inside a transaction.
138+ *
139+ * @template TReturn
140+ *
141+ * @param callable(self): TReturn $callback
142+ *
143+ * @return false|TReturn
144+ */
145+ public function transaction (callable $ callback ): mixed ;
146+
136147 /**
137148 * Returns an instance of the query builder for this connection.
138149 *
Original file line number Diff line number Diff line change @@ -624,6 +624,40 @@ protected function _transRollback(): bool
624624 $ this ->assertSame (['rolled back ' ], $ callbacks );
625625 }
626626
627+ public function testTransactionReturnsFalseWhenTransactionCannotBegin (): void
628+ {
629+ $ callbackRan = false ;
630+
631+ $ db = new class ($ this ->options ) extends MockConnection {
632+ protected function _transBegin (): bool
633+ {
634+ return false ;
635+ }
636+ };
637+
638+ $ result = $ db ->transaction (static function () use (&$ callbackRan ): void {
639+ $ callbackRan = true ;
640+ });
641+
642+ $ this ->assertFalse ($ result );
643+ $ this ->assertFalse ($ callbackRan );
644+ }
645+
646+ public function testTransactionRunsCallbackWhenTransactionsAreDisabled (): void
647+ {
648+ $ db = new MockConnection ($ this ->options );
649+ $ db ->transOff ();
650+
651+ $ result = $ db ->transaction (static function (BaseConnection $ connection ): string {
652+ $ connection ->afterCommit (static function (): void {});
653+
654+ return 'not wrapped ' ;
655+ });
656+
657+ $ this ->assertSame ('not wrapped ' , $ result );
658+ $ this ->assertSame (0 , $ db ->transDepth );
659+ }
660+
627661 public function testCallFunctionDoesNotDoublePrefixAlreadyPrefixedName (): void
628662 {
629663 $ db = new class ($ this ->options ) extends MockConnection {
You can’t perform that action at this time.
0 commit comments