Skip to content

Commit

Permalink
[10.x] Ability to establish connection without using Config Repository (
Browse files Browse the repository at this point in the history
#49527)

* Ability to establish connection without using Config Repository

* StyleCI

* Update src/Illuminate/Database/DatabaseManager.php

Co-authored-by: Dries Vints <dries@vints.be>

* FQN

* FQN

* FQN on tests as well

* FQN

* formatting

---------

Co-authored-by: Dries Vints <dries@vints.be>
Co-authored-by: Taylor Otwell <taylor@laravel.com>
  • Loading branch information
3 people authored Jan 7, 2024
1 parent 29a96eb commit d424ce7
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 5 deletions.
50 changes: 45 additions & 5 deletions src/Illuminate/Database/DatabaseManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down Expand Up @@ -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.
*
Expand Down
107 changes: 107 additions & 0 deletions tests/Integration/Database/DatabaseConnectionsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php

declare(strict_types=1);

namespace Illuminate\Tests\Integration\Database;

use Illuminate\Database\DatabaseManager;
use Illuminate\Database\Events\ConnectionEstablished;
use Illuminate\Events\Dispatcher;
use RuntimeException;

class DatabaseConnectionsTest extends DatabaseTestCase
{
public function testEstablishDatabaseConnection()
{
/** @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)');

$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);
}
}

0 comments on commit d424ce7

Please sign in to comment.