From 3d1ead403e05ee0b9aa93a6ff720704970aec9c8 Mon Sep 17 00:00:00 2001 From: Luke Downing Date: Tue, 21 Sep 2021 19:36:59 +0100 Subject: [PATCH] [8.x] Adds new `RefreshDatabaseLazily` testing trait (#38861) * Adds a new `LazyRefreshDatabase` testing trait and a `QueryExecuting` database event. * Refactor * Refactor * Event test * Naming change * Switches out event for an array of callbacks * Refactor * Refactor * Refactor * Refactor * Refactor * formatting * fix doc block Co-authored-by: Taylor Otwell --- src/Illuminate/Database/Connection.php | 24 +++++++++++++ .../Testing/LazilyRefreshDatabase.php | 34 +++++++++++++++++++ .../Testing/RefreshDatabaseState.php | 7 ++++ src/Illuminate/Support/Facades/DB.php | 1 + tests/Database/DatabaseConnectionTest.php | 11 ++++++ 5 files changed, 77 insertions(+) create mode 100644 src/Illuminate/Foundation/Testing/LazilyRefreshDatabase.php diff --git a/src/Illuminate/Database/Connection.php b/src/Illuminate/Database/Connection.php index c3b148d36fe8..a5d334d0f31c 100755 --- a/src/Illuminate/Database/Connection.php +++ b/src/Illuminate/Database/Connection.php @@ -161,6 +161,13 @@ class Connection implements ConnectionInterface */ protected $pretending = false; + /** + * All of the callbacks that should be invoked before a query is executed. + * + * @var array + */ + protected $beforeExecutingCallbacks = []; + /** * The instance of Doctrine connection. * @@ -641,6 +648,10 @@ public function prepareBindings(array $bindings) */ protected function run($query, $bindings, Closure $callback) { + foreach ($this->beforeExecutingCallbacks as $beforeExecutingCallback) { + $beforeExecutingCallback($query, $bindings, $this); + } + $this->reconnectIfMissingConnection(); $start = microtime(true); @@ -807,6 +818,19 @@ public function disconnect() $this->setPdo(null)->setReadPdo(null); } + /** + * Register a hook to be run just before a database query is executed. + * + * @param \Closure $callback + * @return $this + */ + public function beforeExecuting(Closure $callback) + { + $this->beforeExecutingCallbacks[] = $callback; + + return $this; + } + /** * Register a database query listener with the connection. * diff --git a/src/Illuminate/Foundation/Testing/LazilyRefreshDatabase.php b/src/Illuminate/Foundation/Testing/LazilyRefreshDatabase.php new file mode 100644 index 000000000000..98204cceab48 --- /dev/null +++ b/src/Illuminate/Foundation/Testing/LazilyRefreshDatabase.php @@ -0,0 +1,34 @@ +app->make('db'); + + $database->beforeExecuting(function () { + if (RefreshDatabaseState::$lazilyRefreshed) { + return; + } + + RefreshDatabaseState::$lazilyRefreshed = true; + + $this->baseRefreshDatabase(); + }); + + $this->beforeApplicationDestroyed(function () { + RefreshDatabaseState::$lazilyRefreshed = false; + }); + } +} diff --git a/src/Illuminate/Foundation/Testing/RefreshDatabaseState.php b/src/Illuminate/Foundation/Testing/RefreshDatabaseState.php index 1f33087396f6..a42d3d081bda 100644 --- a/src/Illuminate/Foundation/Testing/RefreshDatabaseState.php +++ b/src/Illuminate/Foundation/Testing/RefreshDatabaseState.php @@ -10,4 +10,11 @@ class RefreshDatabaseState * @var bool */ public static $migrated = false; + + /** + * Indicates if a lazy refresh hook has been invoked. + * + * @var bool + */ + public static $lazilyRefreshed = false; } diff --git a/src/Illuminate/Support/Facades/DB.php b/src/Illuminate/Support/Facades/DB.php index 997f790c0dd3..554dd22030ff 100755 --- a/src/Illuminate/Support/Facades/DB.php +++ b/src/Illuminate/Support/Facades/DB.php @@ -28,6 +28,7 @@ * @method static void enableQueryLog() * @method static void disableQueryLog() * @method static void flushQueryLog() + * @method static \Illuminate\Database\Connection beforeExecuting(\Closure $callback) * @method static void listen(\Closure $callback) * @method static void rollBack(int $toLevel = null) * @method static void setDefaultConnection(string $name) diff --git a/tests/Database/DatabaseConnectionTest.php b/tests/Database/DatabaseConnectionTest.php index 9b160371de67..27ace0b7fc5d 100755 --- a/tests/Database/DatabaseConnectionTest.php +++ b/tests/Database/DatabaseConnectionTest.php @@ -406,6 +406,17 @@ public function testLogQueryFiresEventsIfSet() $connection->logQuery('foo', [], null); } + public function testBeforeExecutingHooksCanBeRegistered() + { + $this->expectExceptionMessage('The callback was fired'); + + $connection = $this->getMockConnection(); + $connection->beforeExecuting(function () { + throw new Exception('The callback was fired'); + }); + $connection->select('foo bar', ['baz']); + } + public function testPretendOnlyLogsQueries() { $connection = $this->getMockConnection();