|
18 | 18 | use PDOStatement;
|
19 | 19 | use Psr\Log\LoggerAwareInterface;
|
20 | 20 | use Psr\Log\LoggerAwareTrait;
|
| 21 | +use Spiral\Database\Exception\ConfigException; |
21 | 22 | use Spiral\Database\Exception\DriverException;
|
22 | 23 | use Spiral\Database\Exception\ReadonlyConnectionException;
|
23 | 24 | use Spiral\Database\Exception\StatementException;
|
@@ -127,6 +128,33 @@ public function __construct(
|
127 | 128 | if ($this->options['readonlySchema']) {
|
128 | 129 | $this->schemaHandler = new ReadonlyHandler($this->schemaHandler);
|
129 | 130 | }
|
| 131 | + |
| 132 | + // Actualize DSN |
| 133 | + $this->updateDSN(); |
| 134 | + } |
| 135 | + |
| 136 | + /** |
| 137 | + * Updates an internal options |
| 138 | + * |
| 139 | + * @return void |
| 140 | + */ |
| 141 | + private function updateDSN(): void |
| 142 | + { |
| 143 | + [$connection, $this->options['username'], $this->options['password']] = $this->parseDSN(); |
| 144 | + |
| 145 | + // Update connection. The DSN field can be located in one of the |
| 146 | + // following keys of the configuration array. |
| 147 | + switch (true) { |
| 148 | + case \array_key_exists('dsn', $this->options): |
| 149 | + $this->options['dsn'] = $connection; |
| 150 | + break; |
| 151 | + case \array_key_exists('addr', $this->options): |
| 152 | + $this->options['addr'] = $connection; |
| 153 | + break; |
| 154 | + default: |
| 155 | + $this->options['connection'] = $connection; |
| 156 | + break; |
| 157 | + } |
130 | 158 | }
|
131 | 159 |
|
132 | 160 | /**
|
@@ -706,19 +734,52 @@ protected function rollbackSavepoint(int $level): void
|
706 | 734 | $this->execute('ROLLBACK TO SAVEPOINT ' . $this->identifier("SVP{$level}"));
|
707 | 735 | }
|
708 | 736 |
|
| 737 | + /** |
| 738 | + * @return array{string, string, string} |
| 739 | + */ |
| 740 | + private function parseDSN(): array |
| 741 | + { |
| 742 | + $dsn = $this->getDSN(); |
| 743 | + |
| 744 | + $user = (string)($this->options['username'] ?? ''); |
| 745 | + $pass = (string)($this->options['password'] ?? ''); |
| 746 | + |
| 747 | + if (\strpos($dsn, '://') > 0) { |
| 748 | + $parts = \parse_url($dsn); |
| 749 | + |
| 750 | + if (!isset($parts['scheme'])) { |
| 751 | + throw new ConfigException('Configuration database scheme must be defined'); |
| 752 | + } |
| 753 | + |
| 754 | + // Update username and password from DSN if not defined. |
| 755 | + $user = $user ?: $parts['user'] ?? ''; |
| 756 | + $pass = $pass ?: $parts['pass'] ?? ''; |
| 757 | + |
| 758 | + // Build new DSN |
| 759 | + $dsn = \sprintf('%s:host=%s', $parts['scheme'], $parts['host'] ?? 'localhost'); |
| 760 | + |
| 761 | + if (isset($parts['port'])) { |
| 762 | + $dsn .= ';port=' . $parts['port']; |
| 763 | + } |
| 764 | + |
| 765 | + if (isset($parts['path']) && \trim($parts['path'], '/')) { |
| 766 | + $dsn .= ';dbname=' . \trim($parts['path'], '/'); |
| 767 | + } |
| 768 | + } |
| 769 | + |
| 770 | + return [$dsn, $user, $pass]; |
| 771 | + } |
| 772 | + |
709 | 773 | /**
|
710 | 774 | * Create instance of configured PDO class.
|
711 | 775 | *
|
712 | 776 | * @return PDO
|
713 | 777 | */
|
714 | 778 | protected function createPDO(): PDO
|
715 | 779 | {
|
716 |
| - return new PDO( |
717 |
| - $this->getDSN(), |
718 |
| - $this->options['username'], |
719 |
| - $this->options['password'], |
720 |
| - $this->options['options'] |
721 |
| - ); |
| 780 | + [$dsn, $user, $pass] = $this->parseDSN(); |
| 781 | + |
| 782 | + return new PDO($dsn, $user, $pass, $this->options['options']); |
722 | 783 | }
|
723 | 784 |
|
724 | 785 | /**
|
|
0 commit comments