diff --git a/src/Illuminate/Database/DatabaseManager.php b/src/Illuminate/Database/DatabaseManager.php index 84602917ea1a..daefffee9f88 100755 --- a/src/Illuminate/Database/DatabaseManager.php +++ b/src/Illuminate/Database/DatabaseManager.php @@ -101,16 +101,39 @@ public function connection($name = null) $this->makeConnection($database), $type ); - if ($this->app->bound('events')) { - $this->app['events']->dispatch( - new ConnectionEstablished($this->connections[$name]) - ); - } + $this->dispatchConnectionEstablishedEvent($this->connections[$name]); } return $this->connections[$name]; } + /** + * Get a database connection instance from the given configuration. + * + * @param string $name + * @param array $config + * @param bool $force + * @return \Illuminate\Database\ConnectionInterface + */ + public function connectUsing(string $name, array $config, bool $force = false) + { + if ($force) { + $this->purge($name); + } + + if (isset($this->connections[$name])) { + throw new RuntimeException("Cannot establish connection [$name] because another connection with that name already exists."); + } + + $connection = $this->configure( + $this->factory->make($config, $name), null + ); + + $this->dispatchConnectionEstablishedEvent($connection); + + return tap($connection, fn ($connection) => $this->connections[$name] = $connection); + } + /** * Parse the connection into an array of the name and read / write type. * @@ -209,6 +232,23 @@ protected function configure(Connection $connection, $type) return $connection; } + /** + * Dispatch the ConnectionEstablished event if the event dispatcher is available. + * + * @param \Illuminate\Database\Connection $connection + * @return void + */ + protected function dispatchConnectionEstablishedEvent(Connection $connection) + { + if (! $this->app->bound('events')) { + return; + } + + $this->app['events']->dispatch( + new ConnectionEstablished($connection) + ); + } + /** * Prepare the read / write mode for database connection instance. * diff --git a/tests/Integration/Database/DatabaseConnectionsTest.php b/tests/Integration/Database/DatabaseConnectionsTest.php new file mode 100644 index 000000000000..dc6b37aa6db7 --- /dev/null +++ b/tests/Integration/Database/DatabaseConnectionsTest.php @@ -0,0 +1,107 @@ +app->make(DatabaseManager::class); + + $connection = $manager->connectUsing('my-phpunit-connection', [ + 'driver' => 'sqlite', + 'database' => ':memory:', + ]); + + $connection->statement('CREATE TABLE test_1 (id INTEGER PRIMARY KEY)'); + + $connection->statement('INSERT INTO test_1 (id) VALUES (1)'); + + $result = $connection->selectOne('SELECT COUNT(*) as total FROM test_1'); + + self::assertSame(1, $result->total); + } + + public function testThrowExceptionIfConnectionAlreadyExists() + { + /** @var \Illuminate\Database\DatabaseManager $manager */ + $manager = $this->app->make(DatabaseManager::class); + + $manager->connectUsing('my-phpunit-connection', [ + 'driver' => 'sqlite', + 'database' => ':memory:', + ]); + + $this->expectException(RuntimeException::class); + + $manager->connectUsing('my-phpunit-connection', [ + 'driver' => 'sqlite', + 'database' => ':memory:', + ]); + } + + public function testOverrideExistingConnection() + { + /** @var \Illuminate\Database\DatabaseManager $manager */ + $manager = $this->app->make(DatabaseManager::class); + + $connection = $manager->connectUsing('my-phpunit-connection', [ + 'driver' => 'sqlite', + 'database' => ':memory:', + ]); + + $connection->statement('CREATE TABLE test_1 (id INTEGER PRIMARY KEY)'); + + $resultBeforeOverride = $connection->select("SELECT name FROM sqlite_master WHERE type='table';"); + + $connection = $manager->connectUsing('my-phpunit-connection', [ + 'driver' => 'sqlite', + 'database' => ':memory:', + ], force: true); + + // After purging a connection of a :memory: SQLite database + // anything that was created before the override will no + // longer be available. It's a new and fresh database + $resultAfterOverride = $connection->select("SELECT name FROM sqlite_master WHERE type='table';"); + + self::assertSame('test_1', $resultBeforeOverride[0]->name); + + self::assertEmpty($resultAfterOverride); + } + + public function testEstablishingAConnectionWillDispatchAnEvent() + { + /** @var \Illuminate\Events\Dispatcher $dispatcher */ + $dispatcher = $this->app->make(Dispatcher::class); + + $event = null; + + $dispatcher->listen(ConnectionEstablished::class, function (ConnectionEstablished $e) use (&$event) { + $event = $e; + }); + + /** @var \Illuminate\Database\DatabaseManager $manager */ + $manager = $this->app->make(DatabaseManager::class); + + $manager->connectUsing('my-phpunit-connection', [ + 'driver' => 'sqlite', + 'database' => ':memory:', + ]); + + self::assertInstanceOf( + ConnectionEstablished::class, + $event, + 'Expected the ConnectionEstablished event to be dispatched when establishing a connection.' + ); + + self::assertSame('my-phpunit-connection', $event->connectionName); + } +}