为啥 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 不同的格式?的主要内容,如果未能解决你的问题,请参考以下文章