diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 970ad3cd..ae0ae2c4 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -54,6 +54,12 @@ jobs: stability: "stable" remove-orm: true + # DBAL 4 + - php-version: "8.2" + dependencies: "highest" + stability: "dev" + remove-orm: true + # Bleeding edge - php-version: "8.2" dependencies: "highest" diff --git a/ConnectionFactory.php b/ConnectionFactory.php index f8d65029..158fecc6 100644 --- a/ConnectionFactory.php +++ b/ConnectionFactory.php @@ -5,19 +5,25 @@ use Doctrine\Common\EventManager; use Doctrine\DBAL\Configuration; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Connection\StaticServerVersionProvider; +use Doctrine\DBAL\ConnectionException; use Doctrine\DBAL\DriverManager; -use Doctrine\DBAL\Exception; use Doctrine\DBAL\Exception as DBALException; use Doctrine\DBAL\Exception\DriverException; +use Doctrine\DBAL\Exception\DriverRequired; +use Doctrine\DBAL\Exception\InvalidWrapperClass; use Doctrine\DBAL\Exception\MalformedDsnException; use Doctrine\DBAL\Platforms\AbstractMySQLPlatform; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Tools\DsnParser; use Doctrine\DBAL\Types\Type; use Doctrine\Deprecations\Deprecation; +use InvalidArgumentException; use function array_merge; +use function class_exists; use function is_subclass_of; +use function method_exists; use function trigger_deprecation; use const PHP_EOL; @@ -63,6 +69,10 @@ public function __construct(array $typesConfig, ?DsnParser $dsnParser = null) */ public function createConnection(array $params, ?Configuration $config = null, ?EventManager $eventManager = null, array $mappingTypes = []) { + if (! method_exists(Connection::class, 'getEventManager') && $eventManager !== null) { + throw new InvalidArgumentException('Passing an EventManager instance is not supported with DBAL > 3'); + } + if (! $this->initialized) { $this->initializeTypes(); } @@ -92,6 +102,10 @@ public function createConnection(array $params, ?Configuration $config = null, ? if (isset($params['wrapperClass'])) { if (! is_subclass_of($params['wrapperClass'], Connection::class)) { + if (class_exists(InvalidWrapperClass::class)) { + throw InvalidWrapperClass::new($params['wrapperClass']); + } + throw DBALException::invalidWrapperClass($params['wrapperClass']); } @@ -99,10 +113,12 @@ public function createConnection(array $params, ?Configuration $config = null, ? $params['wrapperClass'] = null; } - $connection = DriverManager::getConnection($params, $config, $eventManager); + $connection = DriverManager::getConnection(...array_merge([$params, $config], $eventManager ? [$eventManager] : [])); $params = $this->addDatabaseSuffix(array_merge($connection->getParams(), $overriddenOptions)); $driver = $connection->getDriver(); - $platform = $driver->getDatabasePlatform(); + $platform = $driver->getDatabasePlatform( + ...(class_exists(StaticServerVersionProvider::class) ? [new StaticServerVersionProvider($params['serverVersion'] ?? '')] : []) + ); if (! isset($params['charset'])) { if ($platform instanceof AbstractMySQLPlatform) { @@ -134,7 +150,7 @@ public function createConnection(array $params, ?Configuration $config = null, ? $connection = new $wrapperClass($params, $driver, $config, $eventManager); } else { - $connection = DriverManager::getConnection($params, $config, $eventManager); + $connection = DriverManager::getConnection(...array_merge([$params, $config], $eventManager ? [$eventManager] : [])); } if (! empty($mappingTypes)) { @@ -162,7 +178,9 @@ private function getDatabasePlatform(Connection $connection): AbstractPlatform try { return $connection->getDatabasePlatform(); } catch (DriverException $driverException) { - throw new DBALException( + $class = class_exists(DBALException::class) ? DBALException::class : ConnectionException::class; + + throw new $class( 'An exception occurred while establishing a connection to figure out your platform version.' . PHP_EOL . "You can circumvent this by setting a 'server_version' configuration value" . PHP_EOL . PHP_EOL . 'For further information have a look at:' . PHP_EOL . @@ -226,7 +244,7 @@ private function addDatabaseSuffix(array $params): array * URL extracted into individual parameter parts. * @psalm-return Params * - * @throws Exception + * @throws DBALException */ private function parseDatabaseUrl(array $params): array { @@ -237,7 +255,7 @@ private function parseDatabaseUrl(array $params): array try { $parsedParams = $this->dsnParser->parse($params['url']); } catch (MalformedDsnException $e) { - throw new Exception('Malformed parameter "url".', 0, $e); + throw new MalformedDsnException('Malformed parameter "url".', 0, $e); } if (isset($parsedParams['driver'])) { @@ -251,7 +269,11 @@ private function parseDatabaseUrl(array $params): array // 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 Exception::driverRequired($params['url']); + if (class_exists(DriverRequired::class)) { + throw DriverRequired::new($params['url']); + } + + throw DBALException::driverRequired($params['url']); } unset($params['url']); diff --git a/DependencyInjection/DoctrineExtension.php b/DependencyInjection/DoctrineExtension.php index ec6dc79f..0fe693f2 100644 --- a/DependencyInjection/DoctrineExtension.php +++ b/DependencyInjection/DoctrineExtension.php @@ -278,7 +278,8 @@ protected function loadDbalConnection($name, array $connection, ContainerBuilder ->setArguments([ $options, new Reference(sprintf('doctrine.dbal.%s_connection.configuration', $name)), - new Reference(sprintf('doctrine.dbal.%s_connection.event_manager', $name)), + // event manager is only supported on DBAL < 4 + method_exists(Connection::class, 'getEventManager') ? new Reference(sprintf('doctrine.dbal.%s_connection.event_manager', $name)) : null, $connection['mapping_types'], ]); diff --git a/composer.json b/composer.json index b211702a..2286e54b 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ "require": { "php": "^7.4 || ^8.0", "doctrine/cache": "^1.11 || ^2.0", - "doctrine/dbal": "^3.7.0", + "doctrine/dbal": "^3.7.0 || ^4.0", "doctrine/persistence": "^2.2 || ^3", "doctrine/sql-formatter": "^1.0.1", "symfony/cache": "^5.4 || ^6.0 || ^7.0",