zend-db
zend-db copied to clipboard
ZF2 not including port in dsn parameter
This issue has been moved from the zendframework repository as part of the bug migration program as outlined here - http://framework.zend.com/blog/2016-04-11-issue-closures.html
Original Issue: https://api.github.com/repos/zendframework/zendframework/issues/7187 User: @pobrejuanito Created On: 2015-02-06T00:27:48Z Updated At: 2015-02-28T21:09:21Z Body Hi,
I am using 2.2.6, and I am not sure if this is fixed but here it goes:
In Zend\Db\Adapter\Driver\Pdo\Connection.php in method connect() the port parameter doesn't get included in the final $dns string.
Comment
User: @Martin-P Created On: 2015-02-06T11:47:44Z Updated At: 2015-02-06T11:47:44Z Body Should be possible in ZF 2.2.6, because it was added in ZF 2.0.3 through PR #2622.
Comment
User: @pobrejuanito Created On: 2015-02-06T16:07:30Z Updated At: 2015-02-06T16:18:22Z Body there is a case when $dsn is set and $pdodriver is not set. I've added a last "else" case to address this. Now it respects the port in the connect() method:
added $port to list of variable initialization:
$dsn = $username = $password = $hostname = $database = $port = null;
...
if (!isset($dsn) && isset($pdoDriver)) {
$dsn = array();
switch ($pdoDriver) {
case 'sqlite':
$dsn[] = $database;
break;
default:
if (isset($database)) {
$dsn[] = "dbname={$database}";
}
if (isset($hostname)) {
$dsn[] = "host={$hostname}";
}
if (isset($port)) {
$dsn[] = "port={$port}";
}
break;
}
$dsn = $pdoDriver . ':' . implode(';', $dsn);
} elseif (!isset($dsn)) {
throw new Exception\InvalidConnectionParametersException(
'A dsn was not provided or could not be constructed from your parameters',
$this->connectionParameters
);
} else {
// there is a case when $dsn is set and $pdodriver is not set, if so port doesn't get set
if ( $port !== null) {
$dsn .= ';port='.$port;
}
}
It works for me now. Can anyone confirm?
Comment
User: @Martin-P Created On: 2015-02-06T16:27:25Z Updated At: 2015-02-06T16:27:25Z Body
there is a case when $dsn is set and $pdodriver is not set.
Can you elaborate on that? As far as I know you always need a PDO driver name. Can you show what the DSN you use looks like?
Comment
User: @Martin-P
Created On: 2015-02-06T16:38:00Z
Updated At: 2015-02-06T16:38:00Z
Body
Tested your suggestion with $dsn and without $pdodriver and still works fine for me:
public function testDsnWithoutDriverNameAddsPortToDsn()
{
$this->connection->setConnectionParameters(array(
'dsn' => 'host=127.0.0.1;charset=utf8;dbname=foo;port=3306',
));
try {
$this->connection->connect();
} catch (\Exception $e) {
}
$responseString = $this->connection->getDsn();
$this->assertContains('host=127.0.0.1', $responseString);
$this->assertContains('charset=utf8', $responseString);
$this->assertContains('dbname=foo', $responseString);
$this->assertContains('port=3306', $responseString);
}
Comment
User: @pobrejuanito Created On: 2015-02-06T17:21:14Z Updated At: 2015-02-06T17:21:14Z Body This is what I have in my autoload/local.php
'db' => array(
'username' => 'root',
'password' => '',
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=staging;host=127.0.0.1',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
'adapters' => array(
'db1' => array(
'username' => 'api',
'password' => 'pass',
'port' => '30002',
'driver' => 'Pdo',
'dsn' => 'mysql:host=myhost.net;dbname=db1',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
),
'db2' => array(
'username' => 'api',
'password' => 'pass',
'port' => '30002',
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=db2;host=myhost.net,
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
),
),
)
___
### Comment
User: @Martin-P
Created On: 2015-02-06T17:49:00Z
Updated At: 2015-02-06T17:49:00Z
Body
Ah, okay, I see where this is going wrong. You are mixing two ways of setting connection parameters: `dsn` *and* `port`. `Zend\Db\Adapter\Pdo\Connection` expects a `dsn` *or* an array of parameters.
You can fix this by adding the port to your `dsn`:
```php
'dsn' => 'mysql:host=myhost.net;dbname=db1;port=30002',
Not sure this needs fixing at all, perhaps an exception should be thrown when mixing dsn and an array of parameters? Ping @Ocramius
Comment
User: @Martin-P Created On: 2015-02-28T13:48:41Z Updated At: 2015-02-28T13:48:41Z Body Ping @Ocramius @weierophinney Can you clarify if this needs a fix or if you consider it not an issue?
Comment
User: @pobrejuanito Created On: 2015-02-28T20:49:56Z Updated At: 2015-02-28T20:49:56Z Body Have you tried connecting to a different port? I tried to include the port in the string
'dsn' => 'mysql:host=myhost.net;dbname=db1;port=30002'
but it doesn't work. I was pulling my hair out...I had to modifiy Zend/Db/Adapter/Pdo/Connection.php and add the last else case:
if (!isset($dsn) && isset($pdoDriver)) {
$dsn = array();
switch ($pdoDriver) {
case 'sqlite':
$dsn[] = $database;
break;
default:
if (isset($database)) {
$dsn[] = "dbname={$database}";
}
if (isset($hostname)) {
$dsn[] = "host={$hostname}";
}
if (isset($port)) {
$dsn[] = "port={$port}";
}
break;
}
$dsn = $pdoDriver . ':' . implode(';', $dsn);
} elseif (!isset($dsn)) {
throw new Exception\InvalidConnectionParametersException(
'A dsn was not provided or could not be constructed from your parameters',
$this->connectionParameters
);
} else {
// there is a case when $dsn is set and $pdodriver is not set, if so port doesn't get set
if ( $port !== null) {
$dsn .= ';port='.$port;
}
}
Works great now
In the current code, as it loops through, the $dsn string gets rebuilt and leaves out the port specified in the $dsn string.
Comment
User: @Martin-P Created On: 2015-02-28T21:09:21Z Updated At: 2015-02-28T21:09:21Z Body
In the current code, as it loops through, the $dsn string gets rebuilt and leaves out the port specified in the $dsn string.
The problem is Zend\Db\Adapter\Pdo\Connection expects a dsn or an array of parameters. You provide both and Zend\Db\Adapter\Pdo\Connection does not support that.
Please look at my previous comment, I already gave you the solution :wink: When you apply that to your configuration you will get this:
<?php
'db' => array(
'username' => 'root',
'password' => '',
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=staging;host=127.0.0.1',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
'adapters' => array(
'db1' => array(
'username' => 'api',
'password' => 'pass',
// 'port' => '30002', remove this line
'driver' => 'Pdo',
'dsn' => 'mysql:host=myhost.net;dbname=db1;port=30002', // add it here
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
),
'db2' => array(
'username' => 'api',
'password' => 'pass',
// 'port' => '30002', remove this line
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=db2;host=myhost.net;port=30002', // add it here
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
),
),
)
@Martin-P Is this still a problem?
@froschdesign Don't know if it is considered an issue and asked @Ocramius and @weierophinney about it in my comment of 28 Feb 2015.
Sidenote:
Original Issue: https://api.github.com/repos/zendframework/zendframework/issues/7187
Perhaps it is easier to link to the website (remove the api and repos part from the link) instead of linking to a JSON representation of the original post?
@Martin-P Please look under the issue description and you will find the link to the original ticket. (Marked with "Closed")
@Martin-P This can be a problem:
The problem is
Zend\Db\Adapter\Pdo\Connectionexpects a dsn or an array of parameters. You provide both andZend\Db\Adapter\Pdo\Connectiondoes not support that.
This repository has been closed and moved to laminas/laminas-db; a new issue has been opened at https://github.com/laminas/laminas-db/issues/109.