Skip to content

Commit 715f358

Browse files
committed
Connection: support DSN url, replicas+primary, driverClass, defaultTableOptions, keepReplica, sessionMode, wrapperClass
1 parent 266966e commit 715f358

8 files changed

+318
-64
lines changed

.docs/README.md

+57-22
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ Integration of [Doctrine DBAL](https://www.doctrine-project.org/projects/dbal.ht
88
- [Configuration](#configuration)
99
- [Minimal configuration](#minimal-configuration)
1010
- [Advanced configuration](#advanced-configuration)
11+
- [Encoding](#encoding)
12+
- [Replicas](#replicas)
1113
- [Caching](#caching)
1214
- [Types](#types)
1315
- [Debug](#debug)
@@ -43,12 +45,7 @@ nettrine.dbal:
4345
connections:
4446
default:
4547
driver: pdo_pgsql
46-
host: localhost
47-
port: 5432
48-
user: root
49-
password: root
50-
charset: utf8
51-
dbname: nettrine
48+
url: "postgresql://user:password@localhost:5432/dbname"
5249
```
5350

5451
**PostgreSQL**
@@ -58,10 +55,7 @@ nettrine.dbal:
5855
connections:
5956
default:
6057
driver: pdo_pgsql
61-
host: localhost
62-
port: 5432
63-
user: root
64-
password: root
58+
url: "postgresql://user:password@localhost:5432/dbname"
6559
```
6660

6761
**MySQL / MariaDB**
@@ -71,10 +65,7 @@ nettrine.dbal:
7165
connections:
7266
default:
7367
driver: mysqli
74-
host: localhost
75-
port: 3306
76-
user: root
77-
password: root
68+
url: "mysql://user:passoword@localhost:3306/dbname"
7869
```
7970

8071
**SQLite**
@@ -84,9 +75,7 @@ nettrine.dbal:
8475
connections:
8576
default:
8677
driver: pdo_sqlite
87-
password: test
88-
user: test
89-
path: ":memory:"
78+
url: "sqlite:///:memory:"
9079
```
9180

9281
### Advanced configuration
@@ -108,22 +97,28 @@ nettrine.dbal:
10897
charset: <string>
10998
connectstring: <string>
11099
dbname: <string>
100+
defaultTableOptions: <array<string, mixed>>
111101
driver: <'pdo_sqlite', 'sqlite3', 'pdo_mysql', 'mysqli', 'pdo_pgsql', 'pgsql', 'pdo_oci', 'oci8', 'pdo_sqlsrv', 'sqlsrv', 'ibm_db2'>
102+
driverClass: <string>
112103
driverOptions: <array<string, mixed>>
113104
exclusive: <string>
114105
gssencmode: <string>
115106
host: <string>
116107
instancename: <string>
117-
memory: <string>
108+
keepReplica: <bool>
109+
memory: <bool>
118110
password: <string>
119111
path: <string>
120-
persistent: <string>
112+
persistent: <bool>
121113
pooled: <string>
122114
port: <int>
115+
primary: <connection-config>
123116
protocol: <string>
117+
replica: array<string, connection-config>
124118
serverVersion: <string>
125119
service: <string>
126120
servicename: <string>
121+
sessionMode: <int>
127122
ssl_ca: <string>
128123
ssl_capath: <string>
129124
ssl_cert: <string>
@@ -135,7 +130,9 @@ nettrine.dbal:
135130
sslmode: <string>
136131
sslrootcert: <string>
137132
unix_socket: <string>
133+
url: <string>
138134
user: <string>
135+
wrapperClass: <string>
139136
140137
# Config
141138
middlewares: array<string, <service|class-name>>
@@ -155,14 +152,20 @@ nettrine.dbal:
155152
uuid: Ramsey\Uuid\Doctrine\UuidType
156153
157154
connections:
155+
# Short DSN configuration
158156
default:
157+
driver: pdo_pgsql
158+
url: "postgresql://user:password@localhost:5432/dbname?charset=utf8"
159+
160+
# Explicit configuration
161+
second:
159162
driver: pdo_pgsql
160163
host: localhost
161164
port: 5432
162-
user: root
163-
password: root
165+
user: user
166+
password: password
167+
dbname: dbname
164168
charset: utf8
165-
dbname: nettrine
166169
```
167170

168171
Supported drivers:
@@ -182,6 +185,38 @@ Supported drivers:
182185
> [!TIP]
183186
> Take a look at real **Nettrine DBAL** configuration example at [contributte/doctrine-project](https://github.com/contributte/doctrine-project/blob/f226bcf46b9bcce2f68961769a02e507936e4682/config/config.neon).
184187
188+
### Encoding
189+
190+
You can set encoding for your connection.
191+
192+
```neon
193+
nettrine.dbal:
194+
connections:
195+
default:
196+
charset: utf8
197+
defaultTableOptions:
198+
charset: utf8
199+
collate: utf8_unicode_ci
200+
```
201+
202+
### Replicas
203+
204+
Doctrine DBAL supports read replicas. You can define them in the configuration.
205+
206+
```neon
207+
nettrine.dbal:
208+
connections:
209+
default:
210+
driver: pdo_pgsql
211+
wrapperClass: Doctrine\DBAL\Connections\PrimaryReadReplicaConnection
212+
url: "postgresql://user:password@localhost:5432/table?charset=utf8&serverVersion=15.0"
213+
replica:
214+
read1:
215+
url: "postgresql://user:password@read-db1:5432/table?charset=utf8"
216+
read2:
217+
url: "postgresql://user:password@read-db2:5432/table?charset=utf8"
218+
```
219+
185220
### Caching
186221

187222
> [!TIP]

src/DI/DbalExtension.php

+58-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Nettrine\DBAL\DI;
44

5+
use Doctrine\DBAL\Tools\DsnParser;
56
use Nette\DI\CompilerExtension;
67
use Nette\DI\Definitions\Statement;
78
use Nette\PhpGenerator\ClassType;
@@ -21,26 +22,31 @@
2122
* charset: string,
2223
* connectstring: string,
2324
* dbname: string,
25+
* defaultTableOptions: array<string, mixed>,
2426
* driver: string,
27+
* driverClass: string,
2528
* driverOptions: mixed[],
2629
* exclusive: bool,
2730
* gssencmode: string,
2831
* host: string,
2932
* instancename: string,
33+
* keepReplica: bool,
3034
* memory: bool,
3135
* middlewares: array<string, string|array<string>|Statement>,
3236
* password: string,
3337
* path: string,
3438
* persistent: bool,
3539
* pooled: bool,
3640
* port: int,
41+
* primary: array<string, scalar>,
3742
* protocol: string,
3843
* resultCache: mixed,
3944
* schemaAssetsFilter: mixed,
4045
* schemaManagerFactory: mixed,
4146
* serverVersion: string,
4247
* service: bool,
4348
* servicename: string,
49+
* sessionMode: int,
4450
* ssl_ca: string,
4551
* ssl_capath: string,
4652
* ssl_cert: string,
@@ -52,7 +58,8 @@
5258
* sslmode: string,
5359
* sslrootcert: string,
5460
* unix_socket: string,
55-
* user: string
61+
* user: string,
62+
* wrapperClass: string,
5663
* }
5764
*/
5865
class DbalExtension extends CompilerExtension
@@ -61,6 +68,13 @@ class DbalExtension extends CompilerExtension
6168
public const MIDDLEWARE_TAG = 'nettrine.dbal.middleware';
6269
public const MIDDLEWARE_INTERNAL_TAG = 'nettrine.dbal.middleware.internal';
6370
public const CONNECTION_TAG = 'nettrine.dbal.connection';
71+
public const DSN_MAPPING = [
72+
'mysql' => 'mysqli',
73+
'mariadb' => 'mysqli',
74+
'postgres' => 'pdo_pgsql',
75+
'postgresql' => 'pdo_pgsql',
76+
'sqlite' => 'pdo_sqlite',
77+
];
6478

6579
/** @var AbstractPass[] */
6680
protected array $passes = [];
@@ -79,6 +93,18 @@ public function getConfigSchema(): Schema
7993
Expect::type(Statement::class)->required(),
8094
);
8195

96+
$dsnTransformer = static function (mixed $connection) {
97+
if (is_array($connection)) {
98+
if (isset($connection['url'])) {
99+
assert(is_string($connection['url']));
100+
$params = (new DsnParser(self::DSN_MAPPING))->parse($connection['url']);
101+
$connection = array_merge($connection, $params);
102+
}
103+
}
104+
105+
return $connection;
106+
};
107+
82108
return Expect::structure([
83109
'debug' => Expect::structure([
84110
'panel' => Expect::bool(false),
@@ -92,12 +118,15 @@ public function getConfigSchema(): Schema
92118
'charset' => Expect::string(),
93119
'connectstring' => Expect::string(),
94120
'dbname' => Expect::string(),
95-
'driver' => Expect::anyOf('pdo_sqlite', 'sqlite3', 'pdo_mysql', 'mysqli', 'pdo_pgsql', 'pgsql', 'pdo_oci', 'oci8', 'pdo_sqlsrv', 'sqlsrv', 'ibm_db2'),
121+
'defaultTableOptions' => Expect::arrayOf(Expect::mixed(), Expect::string()),
122+
'driver' => Expect::anyOf('pdo_sqlite', 'sqlite3', 'pdo_mysql', 'mysqli', 'pdo_pgsql', 'pgsql', 'pdo_oci', 'oci8', 'pdo_sqlsrv', 'sqlsrv', 'ibm_db2')->required(),
123+
'driverClass' => Expect::string(),
96124
'driverOptions' => Expect::anyOf(Expect::null(), Expect::array()),
97125
'exclusive' => Expect::bool(),
98126
'gssencmode' => Expect::string(),
99127
'host' => Expect::string(),
100128
'instancename' => Expect::string(),
129+
'keepReplica' => Expect::bool(),
101130
'memory' => Expect::bool(),
102131
'password' => Expect::string(),
103132
'path' => Expect::string(),
@@ -108,6 +137,7 @@ public function getConfigSchema(): Schema
108137
'serverVersion' => Expect::string(),
109138
'service' => Expect::bool(),
110139
'servicename' => Expect::string(),
140+
'sessionMode' => Expect::int(),
111141
'ssl_ca' => Expect::string(),
112142
'ssl_capath' => Expect::string(),
113143
'ssl_cert' => Expect::string(),
@@ -119,14 +149,39 @@ public function getConfigSchema(): Schema
119149
'sslmode' => Expect::string(),
120150
'sslrootcert' => Expect::string(),
121151
'unix_socket' => Expect::string(),
152+
'url' => Expect::string(),
122153
'user' => Expect::string(),
154+
'wrapperClass' => Expect::string(),
155+
'replica' => Expect::arrayOf(
156+
Expect::arrayOf(
157+
Expect::scalar(),
158+
Expect::string()
159+
)->before($dsnTransformer),
160+
Expect::string()->required()
161+
),
162+
'primary' => Expect::arrayOf(
163+
Expect::scalar(),
164+
Expect::string()
165+
)->before($dsnTransformer),
123166
// Configuration
124167
'middlewares' => Expect::arrayOf($expectService, Expect::string()->required()),
125168
'resultCache' => (clone $expectService),
126169
'schemaAssetsFilter' => (clone $expectService),
127170
'schemaManagerFactory' => (clone $expectService),
128171
'autoCommit' => Expect::bool(true),
129-
]),
172+
])
173+
->assert(
174+
fn (stdClass $connection) => !(
175+
$connection->url === null
176+
&& $connection->host === null
177+
&& $connection->port === null
178+
&& $connection->path === null
179+
&& $connection->user === null
180+
&& $connection->password === null
181+
),
182+
'Configure DNS url or explicit host, port, user, password, dbname and others.'
183+
)
184+
->before($dsnTransformer),
130185
Expect::string()->required(),
131186
)->min(1)->required(),
132187
]);

0 commit comments

Comments
 (0)