diff --git a/src/Illuminate/Database/DatabaseManager.php b/src/Illuminate/Database/DatabaseManager.php index 8b25573b769..218e6128c0f 100755 --- a/src/Illuminate/Database/DatabaseManager.php +++ b/src/Illuminate/Database/DatabaseManager.php @@ -5,6 +5,7 @@ use Illuminate\Database\Connectors\ConnectionFactory; use Illuminate\Database\Events\ConnectionEstablished; use Illuminate\Support\Arr; +use Illuminate\Support\Collection; use Illuminate\Support\ConfigurationUrlParser; use Illuminate\Support\Str; use Illuminate\Support\Traits\Macroable; @@ -43,9 +44,9 @@ class DatabaseManager implements ConnectionResolverInterface protected $connections = []; /** - * Connection configuration for dynamic connections. + * The dynamically configured (DB::build) connection configurations. * - * @var array + * @var array */ protected $dynamicConnections = []; @@ -117,7 +118,7 @@ public function connection($name = null) public function build(array $config) { if (! isset($config['name'])) { - $config['name'] = 'dynamic_'.Str::uuid(); + $config['name'] = static::calculateDynamicConnectionName($config); } $this->dynamicConnections[$config['name']] = $config; @@ -125,6 +126,19 @@ public function build(array $config) return $this->connectUsing($config['name'], $config, true); } + /** + * Calculate the dynamic connection name for an on-demand connection based on its configuration. + * + * @param array $config + * @return string + */ + public static function calculateDynamicConnectionName(array $config) + { + return 'dynamic_'.md5((new Collection($config))->map(function ($value, $key) { + return $key.(is_string($value) || is_int($value) ? $value : ''); + })->implode('')); + } + /** * Get a database connection instance from the given configuration. * @@ -204,11 +218,9 @@ protected function makeConnection($name) protected function configuration($name) { $name = $name ?: $this->getDefaultConnection(); + $connections = $this->app['config']['database.connections']; - // Attempt to find the config in dynamicConnections first, - // otherwise fallback to the regular connections config. - // If the configuration doesn't exist, we'll throw an exception and bail. $config = $this->dynamicConnections[$name] ?? Arr::get($connections, $name); if (is_null($config)) { diff --git a/tests/Integration/Database/DatabaseConnectionsTest.php b/tests/Integration/Database/DatabaseConnectionsTest.php index d9fd3452f4b..bc8d647ea8c 100644 --- a/tests/Integration/Database/DatabaseConnectionsTest.php +++ b/tests/Integration/Database/DatabaseConnectionsTest.php @@ -136,7 +136,7 @@ public function testTablePrefix() $this->assertSame('', DB::getTablePrefix()); } - public function testDynamicConnectionFailsOnReconnect() + public function testDynamicConnectionDoesntFailOnReconnect() { $connection = DB::build([ 'name' => 'projects', @@ -154,4 +154,22 @@ public function testDynamicConnectionFailsOnReconnect() } } } + + public function testDynamicConnectionWithNoNameDoesntFailOnReconnect() + { + $connection = DB::build([ + 'driver' => 'sqlite', + 'database' => ':memory:', + ]); + + $this->expectNotToPerformAssertions(); + + try { + $connection->reconnect(); + } catch (InvalidArgumentException $e) { + if ($e->getMessage() === 'Database connection [projects] not configured.') { + $this->fail('Dynamic connection should not throw an exception on reconnect.'); + } + } + } }