From 7986e2e2c72f9bad569bdcd662b8a3fac688d863 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Sat, 31 Dec 2022 16:43:55 +0100 Subject: [PATCH] Remove the "url" connection param --- UPGRADE.md | 32 +++++- src/DriverManager.php | 69 +----------- src/Exception/MalformedDsnException.php | 2 - src/Tools/DsnParser.php | 5 +- tests/DriverManagerTest.php | 138 +----------------------- 5 files changed, 33 insertions(+), 213 deletions(-) diff --git a/UPGRADE.md b/UPGRADE.md index eaa8325a527..2d5e11b6018 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -8,11 +8,33 @@ awareness about deprecated code. # Upgrade to 4.0 -## Removed `Connection::PARAM_*_ARRAY` constants +## BC BREAK: Removed the `url` connection parameter + +DBAL ships with a new and configurable DSN parser that can be used to parse a +database URL into connection parameters understood by `DriverManager`. + +### Before + +```php +$connection = DriverManager::getConnection( + ['url' => 'mysql://my-user:t0ps3cr3t@my-host/my-database'] +); +``` + +### After + +```php +$dsnParser = new DsnParser(['mysql' => 'pdo_mysql']); +$connection = DriverManager::getConnection( + $dsnParser->parse('mysql://my-user:t0ps3cr3t@my-host/my-database') +); +``` + +## BC BREAK: Removed `Connection::PARAM_*_ARRAY` constants Use the enum `ArrayParameterType` instead. -## Disallowed partial version numbers in ``serverVersion`` +## BC BREAK: Disallowed partial version numbers in ``serverVersion`` The ``serverVersion`` connection parameter must consist of 3 numbers: @@ -21,7 +43,7 @@ The ``serverVersion`` connection parameter must consist of 3 numbers: +'serverVersion' => '8.0.31' ``` -## Removed `mariadb-` prefix hack +## BC BREAK: Removed `mariadb-` prefix hack Previously, it was necessary to prefix the `serverVersion` parameter with `mariadb-` when using MariaDB. Doing so is now considered invalid, and you @@ -33,11 +55,11 @@ should prefer using the version as returned by `SELECT VERSION();` ``` -## Removed `SchemaDiff::$orphanedForeignKeys` +## BC BREAK: Removed `SchemaDiff::$orphanedForeignKeys` The functionality of automatically dropping the foreign keys referencing the tables being dropped has been removed. -## BC Break: Removed registration of user defined functions for SQLite +## BC BREAK: Removed registration of user defined functions for SQLite DBAL does not register functions for SQLite anymore. The following functions which were previously provided by DBAL have been removed: diff --git a/src/DriverManager.php b/src/DriverManager.php index b229bef258a..b493afa560c 100644 --- a/src/DriverManager.php +++ b/src/DriverManager.php @@ -13,13 +13,9 @@ use Doctrine\DBAL\Exception\DriverRequired; use Doctrine\DBAL\Exception\InvalidDriverClass; use Doctrine\DBAL\Exception\InvalidWrapperClass; -use Doctrine\DBAL\Exception\MalformedDsnException; use Doctrine\DBAL\Exception\UnknownDriver; -use Doctrine\DBAL\Tools\DsnParser; -use Doctrine\Deprecations\Deprecation; use function array_keys; -use function array_merge; use function class_implements; use function in_array; use function is_subclass_of; @@ -62,7 +58,6 @@ * serverVersion?: string, * sharding?: array, * slaves?: array, - * url?: string, * user?: string, * wrapperClass?: class-string, * unix_socket?: string, @@ -158,20 +153,7 @@ private function __construct() public static function getConnection(array $params, ?Configuration $config = null): Connection { $config ??= new Configuration(); - $params = self::parseDatabaseUrl($params); - - // URL support for PrimaryReplicaConnection - if (isset($params['primary'])) { - $params['primary'] = self::parseDatabaseUrl($params['primary']); - } - - if (isset($params['replica'])) { - foreach ($params['replica'] as $key => $replicaParams) { - $params['replica'][$key] = self::parseDatabaseUrl($replicaParams); - } - } - - $driver = self::createDriver($params); + $driver = self::createDriver($params); foreach ($config->getMiddlewares() as $middleware) { $driver = $middleware->wrap($driver); @@ -228,53 +210,4 @@ private static function createDriver(array $params): Driver throw DriverRequired::new(); } - - /** - * Extracts parts from a database URL, if present, and returns an - * updated list of parameters. - * - * @param mixed[] $params The list of parameters. - * @psalm-param Params $params - * - * @return mixed[] A modified list of parameters with info from a database - * URL extracted into indidivual parameter parts. - * @psalm-return Params - */ - private static function parseDatabaseUrl(array $params): array - { - if (! isset($params['url'])) { - return $params; - } - - Deprecation::trigger( - 'doctrine/dbal', - 'https://github.com/doctrine/dbal/pull/5843', - 'The "url" connection parameter is deprecated. Please use %s to parse a database url before calling %s.', - DsnParser::class, - self::class, - ); - - $parser = new DsnParser(); - try { - $parsedParams = $parser->parse($params['url']); - } catch (MalformedDsnException $e) { - throw new InvalidDriverClass('Malformed parameter "url".', 0, $e); - } - - if (isset($parsedParams['driver'])) { - // The requested driver from the URL scheme takes precedence - // over the default custom driver from the connection parameters (if any). - unset($params['driverClass']); - } - - $params = array_merge($params, $parsedParams); - - // If a schemeless connection URL is given, we require a default driver or default custom driver - // as connection parameter. - if (! isset($params['driverClass']) && ! isset($params['driver'])) { - throw DriverRequired::new($params['url']); - } - - return $params; - } } diff --git a/src/Exception/MalformedDsnException.php b/src/Exception/MalformedDsnException.php index f17eeea4a91..eb3056c2fc9 100644 --- a/src/Exception/MalformedDsnException.php +++ b/src/Exception/MalformedDsnException.php @@ -4,8 +4,6 @@ namespace Doctrine\DBAL\Exception; -use InvalidArgumentException; - /** @psalm-immutable */ class MalformedDsnException extends InvalidArgumentException { diff --git a/src/Tools/DsnParser.php b/src/Tools/DsnParser.php index 77f5fc8af4b..758741d26e1 100644 --- a/src/Tools/DsnParser.php +++ b/src/Tools/DsnParser.php @@ -22,8 +22,9 @@ final class DsnParser { /** @param array $schemeMapping An array used to map DSN schemes to DBAL drivers */ - public function __construct(private array $schemeMapping = []) - { + public function __construct( + private readonly array $schemeMapping = [], + ) { } /** diff --git a/tests/DriverManagerTest.php b/tests/DriverManagerTest.php index 8e440a7a545..437ef78101c 100644 --- a/tests/DriverManagerTest.php +++ b/tests/DriverManagerTest.php @@ -5,7 +5,6 @@ namespace Doctrine\DBAL\Tests; use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Connections\PrimaryReadReplicaConnection; use Doctrine\DBAL\Driver; use Doctrine\DBAL\Driver\PDO; use Doctrine\DBAL\Driver\SQLSrv\Driver as SQLSrvDriver; @@ -16,7 +15,6 @@ use PHPUnit\Framework\TestCase; use stdClass; -use function array_intersect_key; use function array_merge; use function in_array; use function is_array; @@ -48,7 +46,8 @@ public function testCustomWrapper(): void $wrapperClass = $wrapper::class; $options = [ - 'url' => 'pdo-sqlite::memory:', + 'driver' => 'sqlite3', + 'memory' => true, 'wrapperClass' => $wrapperClass, ]; @@ -90,79 +89,6 @@ public function testValidDriverClass(): void self::assertInstanceOf(PDO\MySQL\Driver::class, $conn->getDriver()); } - public function testDatabaseUrlPrimaryReplica(): void - { - $options = [ - 'driver' => 'pdo_mysql', - 'primary' => ['url' => 'mysql://foo:bar@localhost:11211/baz'], - 'replica' => [ - 'replica1' => ['url' => 'mysql://foo:bar@localhost:11211/baz_replica'], - ], - 'wrapperClass' => PrimaryReadReplicaConnection::class, - ]; - - $this->expectDeprecationWithIdentifier('https://github.com/doctrine/dbal/pull/5843'); - $conn = DriverManager::getConnection($options); - - $params = $conn->getParams(); - self::assertInstanceOf(PDO\MySQL\Driver::class, $conn->getDriver()); - - $expected = [ - 'user' => 'foo', - 'password' => 'bar', - 'host' => 'localhost', - 'port' => 11211, - 'dbname' => 'baz', - 'driver' => 'pdo_mysql', - 'url' => 'mysql://foo:bar@localhost:11211/baz', - ]; - - self::assertEquals( - [ - 'primary' => $expected, - 'replica' => [ - 'replica1' => array_merge( - $expected, - [ - 'dbname' => 'baz_replica', - 'url' => 'mysql://foo:bar@localhost:11211/baz_replica', - ], - ), - ], - ], - array_intersect_key($params, ['primary' => null, 'replica' => null]), - ); - } - - /** - * @param array|false $expected - * @psalm-param Params|string $url - * - * @dataProvider databaseUrls - */ - public function testDatabaseUrlDeprecated(array|string $url, array|false $expected): void - { - $options = is_array($url) ? $url : ['url' => $url]; - - if ($expected === false) { - $this->expectException(Exception::class); - } - - $this->expectDeprecationWithIdentifier('https://github.com/doctrine/dbal/pull/5843'); - $conn = DriverManager::getConnection($options); - - self::assertNotFalse($expected); - - $params = $conn->getParams(); - foreach ($expected as $key => $value) { - if (in_array($key, ['driver', 'driverClass'], true)) { - self::assertInstanceOf($value, $conn->getDriver()); - } else { - self::assertEquals($value, $params[$key]); - } - } - } - /** * @param array|string $url * @param array|false $expected @@ -172,12 +98,6 @@ public function testDatabaseUrlDeprecated(array|string $url, array|false $expect public function testDatabaseUrl(array|string $url, array|false $expected): void { if (is_array($url)) { - if (isset($url['driverClass'])) { - self::markTestSkipped( - 'Legacy test case: Merging driverClass into the parsed parameters has to be done in userland now.', - ); - } - ['url' => $url] = $options = $url; unset($options['url']); } else { @@ -386,60 +306,6 @@ public function databaseUrls(): iterable 'driverClass' => $driverClass, ], ], - 'URL without scheme but driver and custom driver' => [ - [ - 'url' => '//foo:bar@localhost/baz', - 'driver' => 'pdo_mysql', - 'driverClass' => $driverClass, - ], - [ - 'user' => 'foo', - 'password' => 'bar', - 'host' => 'localhost', - 'dbname' => 'baz', - 'driverClass' => $driverClass, - ], - ], - 'URL with default driver' => [ - [ - 'url' => 'pdo-mysql://foo:bar@localhost/baz', - 'driver' => 'sqlite', - ], - [ - 'user' => 'foo', - 'password' => 'bar', - 'host' => 'localhost', - 'dbname' => 'baz', - 'driver' => PDO\MySQL\Driver::class, - ], - ], - 'URL with default custom driver' => [ - [ - 'url' => 'pdo-mysql://foo:bar@localhost/baz', - 'driverClass' => $driverClass, - ], - [ - 'user' => 'foo', - 'password' => 'bar', - 'host' => 'localhost', - 'dbname' => 'baz', - 'driver' => PDO\MySQL\Driver::class, - ], - ], - 'URL with default driver and default custom driver' => [ - [ - 'url' => 'pdo-mysql://foo:bar@localhost/baz', - 'driver' => 'sqlite', - 'driverClass' => $driverClass, - ], - [ - 'user' => 'foo', - 'password' => 'bar', - 'host' => 'localhost', - 'dbname' => 'baz', - 'driver' => PDO\MySQL\Driver::class, - ], - ], ]; } }