【问题标题】: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)?

【问题讨论】:

    标签: php mysql postgresql pdo


    【解决方案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);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-06-04
        • 1970-01-01
        • 2016-04-01
        • 2013-11-10
        • 2015-07-23
        • 2019-02-07
        • 1970-01-01
        相关资源
        最近更新 更多