ConnectionFactory.php 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Infrastructure\Db;
  4. use Doctrine\DBAL\Connection;
  5. use Doctrine\DBAL\DriverManager;
  6. use InvalidArgumentException;
  7. /**
  8. * Builds a Doctrine DBAL Connection from the api's `db` settings.
  9. *
  10. * For SQLite we apply the four PRAGMAs the spec mandates on each new
  11. * connection (WAL journaling, normal sync, busy timeout, foreign keys on).
  12. */
  13. final class ConnectionFactory
  14. {
  15. /**
  16. * @param array{
  17. * driver: string,
  18. * sqlite_path: string,
  19. * mysql_host: string,
  20. * mysql_port: int,
  21. * mysql_database: string,
  22. * mysql_username: string,
  23. * mysql_password: string
  24. * } $settings
  25. */
  26. public function __construct(private readonly array $settings)
  27. {
  28. }
  29. public function create(): Connection
  30. {
  31. $driver = $this->settings['driver'];
  32. if ($driver === 'sqlite') {
  33. $path = $this->settings['sqlite_path'];
  34. if ($path === ':memory:') {
  35. $params = [
  36. 'driver' => 'pdo_sqlite',
  37. 'memory' => true,
  38. ];
  39. } else {
  40. $params = [
  41. 'driver' => 'pdo_sqlite',
  42. 'path' => $path,
  43. ];
  44. }
  45. $connection = DriverManager::getConnection($params);
  46. self::applySqlitePragmas($connection);
  47. return $connection;
  48. }
  49. if ($driver === 'mysql') {
  50. $params = [
  51. 'driver' => 'pdo_mysql',
  52. 'host' => $this->settings['mysql_host'],
  53. 'port' => $this->settings['mysql_port'],
  54. 'dbname' => $this->settings['mysql_database'],
  55. 'user' => $this->settings['mysql_username'],
  56. 'password' => $this->settings['mysql_password'],
  57. 'charset' => 'utf8mb4',
  58. ];
  59. return DriverManager::getConnection($params);
  60. }
  61. throw new InvalidArgumentException(sprintf('Unsupported DB_DRIVER: %s', $driver));
  62. }
  63. private static function applySqlitePragmas(Connection $connection): void
  64. {
  65. $connection->executeStatement('PRAGMA journal_mode = WAL');
  66. $connection->executeStatement('PRAGMA synchronous = NORMAL');
  67. $connection->executeStatement('PRAGMA busy_timeout = 5000');
  68. $connection->executeStatement('PRAGMA foreign_keys = ON');
  69. }
  70. }