Skip to content

Commit a82dc3c

Browse files
authored
Merge pull request #310 from richard67/3.x-dev-portnumber
[3.x] Allow to specify port number or UNIX socket in host option also for MySQL (PDO) and PostgreSQL (PDO)
2 parents 3927dea + 66fc236 commit a82dc3c

3 files changed

Lines changed: 65 additions & 54 deletions

File tree

src/DatabaseDriver.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1893,4 +1893,63 @@ public function updateObject($table, &$object, $key, $nulls = false)
18931893

18941894
return true;
18951895
}
1896+
1897+
/**
1898+
* Extract pure host name (or IP address) and port or socket from host name option.
1899+
*
1900+
* @param integer $defaultPort The default port number to be used if no port is given.
1901+
*
1902+
* @since __DEPLOY_VERSION__
1903+
*/
1904+
protected function setHostPortSocket($defaultPort)
1905+
{
1906+
$port = $this->options['port'] ?? $defaultPort;
1907+
1908+
if (preg_match('/^unix:(?P<socket>[^:]+)$/', $this->options['host'], $matches)) {
1909+
// UNIX socket URI, e.g. 'unix:/path/to/unix/socket.sock'
1910+
$this->options['host'] = null;
1911+
$this->options['socket'] = $matches['socket'];
1912+
$this->options['port'] = null;
1913+
} elseif (
1914+
preg_match(
1915+
'/^(?P<host>((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))(:(?P<port>.+))?$/',
1916+
$this->options['host'],
1917+
$matches
1918+
)
1919+
) {
1920+
// It's an IPv4 address with or without port
1921+
$this->options['host'] = $matches['host'];
1922+
1923+
if (!empty($matches['port'])) {
1924+
$port = $matches['port'];
1925+
}
1926+
} elseif (preg_match('/^(?P<host>\[.*\])(:(?P<port>.+))?$/', $this->options['host'], $matches)) {
1927+
// We assume square-bracketed IPv6 address with or without port, e.g. [fe80:102::2%eth1]:3306
1928+
$this->options['host'] = $matches['host'];
1929+
1930+
if (!empty($matches['port'])) {
1931+
$port = $matches['port'];
1932+
}
1933+
} elseif (preg_match('/^(?P<host>(\w+:\/{2,3})?[a-z0-9\.\-]+)(:(?P<port>[^:]+))?$/i', $this->options['host'], $matches)) {
1934+
// Named host (e.g example.com or localhost) with or without port
1935+
$this->options['host'] = $matches['host'];
1936+
1937+
if (!empty($matches['port'])) {
1938+
$port = $matches['port'];
1939+
}
1940+
} elseif (preg_match('/^:(?P<port>[^:]+)$/', $this->options['host'], $matches)) {
1941+
// Empty host, just port, e.g. ':3306'
1942+
$this->options['host'] = 'localhost';
1943+
$port = $matches['port'];
1944+
}
1945+
1946+
// ... else we assume normal (naked) IPv6 address, so host and port stay as they are or default
1947+
1948+
// Get the port number or socket name
1949+
if (is_numeric($port)) {
1950+
$this->options['port'] = (int) $port;
1951+
} else {
1952+
$this->options['socket'] = $port;
1953+
}
1954+
}
18961955
}

src/Mysqli/MysqliDriver.php

Lines changed: 2 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -198,58 +198,8 @@ public function connect()
198198
throw new UnsupportedAdapterException('The MySQLi extension is not available');
199199
}
200200

201-
/*
202-
* Unlike mysql_connect(), mysqli_connect() takes the port and socket as separate arguments. Therefore, we
203-
* have to extract them from the host string.
204-
*/
205-
$port = isset($this->options['port']) ? $this->options['port'] : 3306;
206-
207-
if (preg_match('/^unix:(?P<socket>[^:]+)$/', $this->options['host'], $matches)) {
208-
// UNIX socket URI, e.g. 'unix:/path/to/unix/socket.sock'
209-
$this->options['host'] = null;
210-
$this->options['socket'] = $matches['socket'];
211-
$this->options['port'] = null;
212-
} elseif (
213-
preg_match(
214-
'/^(?P<host>((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))(:(?P<port>.+))?$/',
215-
$this->options['host'],
216-
$matches
217-
)
218-
) {
219-
// It's an IPv4 address with or without port
220-
$this->options['host'] = $matches['host'];
221-
222-
if (!empty($matches['port'])) {
223-
$port = $matches['port'];
224-
}
225-
} elseif (preg_match('/^(?P<host>\[.*\])(:(?P<port>.+))?$/', $this->options['host'], $matches)) {
226-
// We assume square-bracketed IPv6 address with or without port, e.g. [fe80:102::2%eth1]:3306
227-
$this->options['host'] = $matches['host'];
228-
229-
if (!empty($matches['port'])) {
230-
$port = $matches['port'];
231-
}
232-
} elseif (preg_match('/^(?P<host>(\w+:\/{2,3})?[a-z0-9\.\-]+)(:(?P<port>[^:]+))?$/i', $this->options['host'], $matches)) {
233-
// Named host (e.g example.com or localhost) with or without port
234-
$this->options['host'] = $matches['host'];
235-
236-
if (!empty($matches['port'])) {
237-
$port = $matches['port'];
238-
}
239-
} elseif (preg_match('/^:(?P<port>[^:]+)$/', $this->options['host'], $matches)) {
240-
// Empty host, just port, e.g. ':3306'
241-
$this->options['host'] = 'localhost';
242-
$port = $matches['port'];
243-
}
244-
245-
// ... else we assume normal (naked) IPv6 address, so host and port stay as they are or default
246-
247-
// Get the port number or socket name
248-
if (is_numeric($port)) {
249-
$this->options['port'] = (int) $port;
250-
} else {
251-
$this->options['socket'] = $port;
252-
}
201+
// Extract host and port or socket from host option
202+
$this->setHostPortSocket(3306);
253203

254204
$this->connection = mysqli_init();
255205

src/Pdo/PdoDriver.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,8 @@ public function connect()
209209
break;
210210

211211
case 'mysql':
212-
$this->options['port'] = $this->options['port'] ?? 3306;
212+
// Extract host and port or socket from host option
213+
$this->setHostPortSocket(3306);
213214

214215
if ($this->options['socket'] !== null) {
215216
$format = 'mysql:unix_socket=#SOCKET#;dbname=#DBNAME#;charset=#CHARSET#';
@@ -257,7 +258,8 @@ public function connect()
257258
break;
258259

259260
case 'pgsql':
260-
$this->options['port'] = $this->options['port'] ?? 5432;
261+
// Extract host and port or socket from host option
262+
$this->setHostPortSocket(5432);
261263

262264
if ($this->options['socket'] !== null) {
263265
$format = 'pgsql:host=#SOCKET#;dbname=#DBNAME#';

0 commit comments

Comments
 (0)