342

取而代之的是,我们在使用 mysqli 和 PDO 来处理诸如准备好的语句和事务支持之类的东西之间进行划分。有些项目使用一个,有些项目使用另一个。我们几乎不可能迁移到另一个 RDBMS。

我更喜欢 PDO 的唯一原因是它允许为准备好的语句命名参数,而据我所知 mysqli 不允许。

当我们整合我们的项目以仅使用一种方法时,选择其中一种作为标准是否还有其他优点和缺点?

4

13 回答 13

243

Well, you could argue with the object oriented aspect, the prepared statements, the fact that it becomes a standard, etc. But I know that most of the time, convincing somebody works better with a killer feature. So there it is:

A really nice thing with PDO is you can fetch the data, injecting it automatically in an object. If you don't want to use an ORM (cause it's a just a quick script) but you do like object mapping, it's REALLY cool :

class Student {

    public $id;
    public $first_name;
    public $last_name

    public function getFullName() {
        return $this->first_name.' '.$this->last_name
    }
}

try 
{
    $dbh = new PDO("mysql:host=$hostname;dbname=school", $username, $password)

    $stmt = $dbh->query("SELECT * FROM students");

    /* MAGIC HAPPENS HERE */

    $stmt->setFetchMode(PDO::FETCH_INTO, new Student);


    foreach($stmt as $student)
    {
        echo $student->getFullName().'<br />';
    } 

    $dbh = null;
}
catch(PDOException $e)
{
    echo $e->getMessage();
}
于 2008-12-15T16:49:17.780 回答
57

将应用程序从一个数据库移动到另一个数据库并不常见,但迟早您可能会发现自己正在使用不同的 RDBMS 处理另一个项目。如果您在家中使用 PDO,那么此时至少要少学一件事。

除此之外,我发现 PDO API 更直观一点,而且感觉更真正面向对象。mysqli 感觉它只是一个被客观化的程序 API,如果你明白我的意思的话。简而言之,我发现 PDO 更易于使用,但这当然是主观的。

于 2008-08-17T09:55:03.420 回答
25

在我看来,我开始使用 PDO 是因为语句支持更好。我正在使用 ActiveRecord-esque 数据访问层,实现动态生成的语句要容易得多。MySQLi 的参数绑定必须在单个函数/方法调用中完成,因此如果您直到运行时才知道要绑定多少个参数,您将被迫使用call_user_func_array()(我相信这是正确的函数名称)进行选择. 忘记简单的动态结果绑定。

最重要的是,我喜欢 PDO,因为它是一个非常合理的抽象级别。在您不想编写 SQL 的完全抽象的系统中使用它很容易,但它也可以很容易地使用更优化的纯查询类型的系统,或者混合搭配两者。

于 2008-09-08T14:17:40.213 回答
17

PDO 是标准,它是大多数开发人员期望使用的。mysqli 本质上是针对特定问题的定制解决方案,但它具有其他特定于 DBMS 的库的所有问题。PDO 是所有辛勤工作和聪明思考的地方。

于 2008-09-10T21:56:31.030 回答
15

这里还有一点要记住:目前(PHP 5.2)PDO 库是有缺陷的。它充满了奇怪的错误。例如:在PDOStatement变量中存储 a 之前,该变量应该unset()避免大量错误。其中大部分已在 PHP 5.3 中修复,它们将在 2009 年初在 PHP 5.3 中发布,其中可能会有许多其他错误。如果你想要一个稳定的版本,你应该专注于使用 PDO for PHP 6.1,如果你想帮助社区,你应该专注于使用 PDO for PHP 5.3。

于 2008-12-15T15:45:02.933 回答
10

关于 PDO 的另一个显着(好的)区别是它的PDO::quote()方法会自动添加封闭引号,而mysqli::real_escape_string()(和类似的)不会:

PDO::quote() 使用适合底层驱动程序的引用样式在输入字符串周围放置引号(如果需要)并转义输入字符串中的特殊字符。

于 2011-07-26T04:20:45.663 回答
8

如果您的站点/Web 应用程序真正成为现实,那么 PDO 将使扩展变得更加容易,因为您可以每天设置主连接和从连接以在数据库中分配负载,而且 PHP 正朝着将 PDO 作为标准迁移。

PDO 信息

扩展 Web 应用程序

于 2012-04-20T22:58:40.663 回答
6

在执行速度方面 MySQLi 胜出,但除非你有一个使用 MySQLi 的好的包装器,否则它处理准备好的语句的函数很糟糕。

我的仍然有错误,但如果有人想要它,就在这里

简而言之,如果您正在寻找速度增益,那么 MySQLi;如果你想要易用性,那么 PDO。

于 2009-04-10T06:04:27.493 回答
5

我个人使用 PDO,但我认为这主要是一个偏好问题。

PDO 有一些有助于防止 SQL 注入(prepared statements)的特性,但是如果你小心你的 SQL,你也可以使用 mysqli 来实现。

迁移到另一个数据库并不是使用 PDO 的主要原因。只要不使用“特殊 SQL 功能”,就可以从一个 DB 切换到另一个 DB。但是,一旦您使用例如“SELECT ... LIMIT 1”,您就不能转到“SELECT TOP 1 ...”的 MS-SQL。所以这无论如何都是有问题的。

于 2008-08-19T18:55:06.277 回答
5

编辑答案。

在对这两个 API 有一些经验之后,我会说有 2 个阻塞级功能使 mysqli 无法与本机准备语句一起使用。
他们已经在 2 个出色的(但被低估的)答案中提到:

  1. 将值绑定到任意数量的占位符
  2. 以数组的形式返回数据

(在这个答案中也提到了)

由于某种原因,mysqli 两者都失败了。
现在它对第二个(get_result)有了一些改进,但它只适用于 mysqlnd 安装,这意味着你不能在脚本中依赖这个函数。

然而,直到今天它还没有按值绑定。

所以,只有一个选择:PDO

所有其他原因,例如

  • 命名占位符(这种语法糖被高估了)
  • 不同的数据库支持(实际上没有人使用过它)
  • 获取对象(只是无用的语法糖)
  • 速度差(没有)

没有任何重要意义。

同时这两个API都缺乏一些真正重要的特性,比如

  • 标识符占位符
  • 复杂数据类型的占位符,使动态绑定不那么繁琐
  • 更短的应用程序代码。

因此,为了满足现实生活的需求,必须基于这些 API 之一创建自己的抽象库,实现手动解析的占位符。在这种情况下,我更喜欢 mysqli,因为它的抽象级别较低。

于 2013-01-13T13:06:20.920 回答
4

在我的基准脚本中,每种方法都测试了 10000 次,并打印了每种方法的总时间差。您应该根据自己的配置进行此操作,我相信结果会有所不同!

这些是我的结果:

  • "SELECT NULL" -> PGO()快了 ~ 0.35 秒
  • "SHOW TABLE STATUS" -> mysqli()快了 ~ 2.3 秒
  • "SELECT * FROM users" -> mysqli()快了约 33 秒

注意:通过对 mysqli 使用 ->fetch_row(),列名不会添加到数组中,我在 PGO 中没有找到这样做的方法。但即使我使用 ->fetch_array() ,mysqli 也比 PGO 稍慢但仍比 PGO 快(SELECT NULL 除外)。

于 2010-10-14T20:43:32.693 回答
3

PDO 有一点我不喜欢 MySQLi 的东西,那就是 PDO 能够将结果作为指定类类型的对象(例如$pdo->fetchObject('MyClass'))返回。MySQLifetch_object()只会返回一个stdClass对象。

于 2008-09-24T14:01:54.383 回答
-4

有一件事要记住。

Mysqli 不支持 fetch_assoc() 函数,该函数将返回带有表示列名的键的列。当然可以编写你自己的函数来做到这一点,它甚至不是很长,但我真的很难写它(对于非信徒:如果你觉得这很容易,请自己尝试一下,不要'不要作弊 :) )

于 2008-09-24T13:45:36.497 回答