为啥 PHP PDO DSN 是 MySQL 与 PostgreSQL 不同的格式?

Posted

技术标签:

【中文标题】为啥 PHP PDO DSN 是 MySQL 与 PostgreSQL 不同的格式?【英文标题】:Why is PHP PDO DSN a different format for MySQL versus PostgreSQL?为什么 PHP PDO DSN 是 MySQL 与 PostgreSQL 不同的格式? 【发布时间】:2010-09-19 05:43:00 【问题描述】:

当我使用 PDO 连接到 mysql 数据库时,我需要的连接方式是:

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

但是,对于 PostgreSQL,DSN 更加标准(IMO):

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

MySQL 不能使用单个字符串有什么原因吗?或者这仅仅是因为我使用的版本(php 5.2、MySQL 5.0、PostgreSQL 8.1)?

【问题讨论】:

【参考方案1】:

作为实现这两者的人,我可以告诉你,原因是通过将字符串按原样传递给 postgres(和 ODBC),这些数据库的 PDO 驱动程序代码不需要作为底层库进行更新添加新功能。

由于 MySQL 没有自己的连接字符串解析代码,我们发明了一种将数据传递到底层 MySQL 函数调用的机制,这些函数调用具有非常特定的 API 和固定参数。

没有意外;这是非常刻意的。

【讨论】:

你无法与 Wez 的回答争论……这怎么还没被接受? :) 我不明白。如果您无论如何都必须解析 MySQL 的字符串,为什么不从 DSN 中解析出用户名和密码呢?现在我们必须使用多个字段而不仅仅是一个连接字符串;或从半有效的 mysql DSN 中解析并删除用户名/密码;或发明一种适用于两者的新连接字符串格式。这些解决方案中的任何一个都很容易实现,但必须在用户空间中为每个使用 PDO 的库实现。呃。 感谢您的回复,为糟糕的设计感到羞耻。 DSN 背后的整个想法是拥有一种标准格式,而这种选择打破了最流行的引擎之一的这一点。 哇,真的是把 PDO 写进 PHP 的那个人吗?传奇的!也谢谢你的回答。 所以你创建了一个统一的数据库接口,然后故意让 DSN 的行为根据你想连接的数据库类型而有所不同?所有应有的尊重你的工作,但你们高吗!?【参考方案2】:

这已在 PHP 7.4 中得到解决,如 the new features 所示。

我已经在本地确认可以写了:

$dbh = new PDO('mysql:host=localhost;dbname=my_db;charset=utf8mb4;user=root;password=')

【讨论】:

【参考方案3】:

是的,这种 API 不一致是一个主要的烦恼。

作为一种解决方法,我使用查询字符串语法将实际的 DSN 字符串与可选的用户名和密码打包在一起——然后像这样解析和构造:

parse_str($connection_string, $params);

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

所以对于 PostgreSQL,使用 $connection_string 之类的:

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

对于 MySQL,使用如下字符串:

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

有点蹩脚,但它很简单而且很有效。

【讨论】:

$dsn = "mysql:host=".$this->servname.";dbname=".$this->dbname.";char=".$this->char;这是正确的语法还是我在错误的地方得到了双引号? 尝试改用sprintf -- 更简洁。【参考方案4】:

这个问题已经有 10 多年的历史了,但是每次我创建一个使用 PDO 的新项目时,我仍然会在这里结束......我正在这里编写我的解决方案,以便下次我可以省去自己的麻烦:P

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);
    

【讨论】:

以上是关于为啥 PHP PDO DSN 是 MySQL 与 PostgreSQL 不同的格式?的主要内容,如果未能解决你的问题,请参考以下文章

php pdo学习笔记

2017 6 2php用PDO链接数据库前测试

php使用PDO连接mysql数据库

PDO

<php>PDO链接方法

php部分---PDO;