Home » Php » Why is PHP PDO DSN a different format for MySQL versus PostgreSQL?

Why is PHP PDO DSN a different format for MySQL versus PostgreSQL?

Posted by: admin April 23, 2020 Leave a comment

Questions:

When I connect to a MySQL database using PDO, the way I need to connect is:

$pdoConnection = new PDO("mysql:host=hostname;dbname=databasename",user,password);

But, for PostgreSQL, the DSN is more standard (IMO):

$pdoConnection = new PDO("pgsql:host=hostname;dbname=databasename;user=username;password=thepassword");

Is there any reason why MySQL cannot use a single string? Or is this just because of the versions I am using (PHP 5.2, MySQL 5.0, PostgreSQL 8.1)?

How to&Answers:

As the person that implemented both, I can tell you that the reason is that by passing the string through as-is to postgres (and ODBC) the PDO driver code for those databases does not need to be updated as the underlying library adds new features.

Since MySQL does not have its own connection string parsing code, we invented a mechanism for passing data in to the underlying MySQL function calls, which have a very specific API with fixed parameters.

No accident; it’s very deliberate.

Answer:

Yep, this API inconsistency is a major annoyance.

As a work-around, I pack the actual DSN string with an optional username and password using query-string syntax – then parse and construct like this:

parse_str($connection_string, $params);

$pdo = new PDO($params['dsn'], @$params['username'], @$params['password']);

So for PostgreSQL, use a $connection_string like:

dsn=pgsql:host=localhost;dbname=test;user=root;password=root

And for MySQL, use a string like:

dsn=mysql:host=localhost;dbname=testdb&username=root&password=root

Kind of lame, but it’s simple and it works.

Answer:

This question is more than 10 years old, but I still end up here every time I create a new project that uses PDO… I’m writing my solution here so that I can save myself the trouble next time 😛

class MyPDO extends PDO {
    public function __construct($dsn, $options = null) {
        $user=null;
        $pass=null;

        if (preg_match("/user=([^;]*)/", $dsn, $matches)) {
            $user=$matches[1];
        }
        if (preg_match("/password=([^;]*)/", $dsn, $matches)) {
            $pass=$matches[1];
        }

        parent::__construct($dsn, $user, $pass, $options);
    }
}