取而代之的是,我们在使用 mysqli 和 PDO 来处理诸如准备好的语句和事务支持之类的东西之间进行划分。有些项目使用一个,有些项目使用另一个。我们几乎不可能迁移到另一个 RDBMS。
我更喜欢 PDO 的唯一原因是它允许为准备好的语句命名参数,而据我所知 mysqli 不允许。
当我们整合我们的项目以仅使用一种方法时,选择其中一种作为标准是否还有其他优点和缺点?
取而代之的是,我们在使用 mysqli 和 PDO 来处理诸如准备好的语句和事务支持之类的东西之间进行划分。有些项目使用一个,有些项目使用另一个。我们几乎不可能迁移到另一个 RDBMS。
我更喜欢 PDO 的唯一原因是它允许为准备好的语句命名参数,而据我所知 mysqli 不允许。
当我们整合我们的项目以仅使用一种方法时,选择其中一种作为标准是否还有其他优点和缺点?
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();
}
将应用程序从一个数据库移动到另一个数据库并不常见,但迟早您可能会发现自己正在使用不同的 RDBMS 处理另一个项目。如果您在家中使用 PDO,那么此时至少要少学一件事。
除此之外,我发现 PDO API 更直观一点,而且感觉更真正面向对象。mysqli 感觉它只是一个被客观化的程序 API,如果你明白我的意思的话。简而言之,我发现 PDO 更易于使用,但这当然是主观的。
在我看来,我开始使用 PDO 是因为语句支持更好。我正在使用 ActiveRecord-esque 数据访问层,实现动态生成的语句要容易得多。MySQLi 的参数绑定必须在单个函数/方法调用中完成,因此如果您直到运行时才知道要绑定多少个参数,您将被迫使用call_user_func_array()
(我相信这是正确的函数名称)进行选择. 忘记简单的动态结果绑定。
最重要的是,我喜欢 PDO,因为它是一个非常合理的抽象级别。在您不想编写 SQL 的完全抽象的系统中使用它很容易,但它也可以很容易地使用更优化的纯查询类型的系统,或者混合搭配两者。
PDO 是标准,它是大多数开发人员期望使用的。mysqli 本质上是针对特定问题的定制解决方案,但它具有其他特定于 DBMS 的库的所有问题。PDO 是所有辛勤工作和聪明思考的地方。
这里还有一点要记住:目前(PHP 5.2)PDO 库是有缺陷的。它充满了奇怪的错误。例如:在PDOStatement
变量中存储 a 之前,该变量应该unset()
避免大量错误。其中大部分已在 PHP 5.3 中修复,它们将在 2009 年初在 PHP 5.3 中发布,其中可能会有许多其他错误。如果你想要一个稳定的版本,你应该专注于使用 PDO for PHP 6.1,如果你想帮助社区,你应该专注于使用 PDO for PHP 5.3。
关于 PDO 的另一个显着(好的)区别是它的PDO::quote()
方法会自动添加封闭引号,而mysqli::real_escape_string()
(和类似的)不会:
PDO::quote() 使用适合底层驱动程序的引用样式在输入字符串周围放置引号(如果需要)并转义输入字符串中的特殊字符。
如果您的站点/Web 应用程序真正成为现实,那么 PDO 将使扩展变得更加容易,因为您可以每天设置主连接和从连接以在数据库中分配负载,而且 PHP 正朝着将 PDO 作为标准迁移。
在执行速度方面 MySQLi 胜出,但除非你有一个使用 MySQLi 的好的包装器,否则它处理准备好的语句的函数很糟糕。
我的仍然有错误,但如果有人想要它,就在这里。
简而言之,如果您正在寻找速度增益,那么 MySQLi;如果你想要易用性,那么 PDO。
我个人使用 PDO,但我认为这主要是一个偏好问题。
PDO 有一些有助于防止 SQL 注入(prepared statements)的特性,但是如果你小心你的 SQL,你也可以使用 mysqli 来实现。
迁移到另一个数据库并不是使用 PDO 的主要原因。只要不使用“特殊 SQL 功能”,就可以从一个 DB 切换到另一个 DB。但是,一旦您使用例如“SELECT ... LIMIT 1”,您就不能转到“SELECT TOP 1 ...”的 MS-SQL。所以这无论如何都是有问题的。
编辑答案。
在对这两个 API 有一些经验之后,我会说有 2 个阻塞级功能使 mysqli 无法与本机准备语句一起使用。
他们已经在 2 个出色的(但被低估的)答案中提到:
(在这个答案中也提到了)
由于某种原因,mysqli 两者都失败了。
现在它对第二个(get_result)有了一些改进,但它只适用于 mysqlnd 安装,这意味着你不能在脚本中依赖这个函数。
然而,直到今天它还没有按值绑定。
所以,只有一个选择:PDO
所有其他原因,例如
没有任何重要意义。
同时这两个API都缺乏一些真正重要的特性,比如
因此,为了满足现实生活的需求,必须基于这些 API 之一创建自己的抽象库,实现手动解析的占位符。在这种情况下,我更喜欢 mysqli,因为它的抽象级别较低。
在我的基准脚本中,每种方法都测试了 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 除外)。
PDO 有一点我不喜欢 MySQLi 的东西,那就是 PDO 能够将结果作为指定类类型的对象(例如$pdo->fetchObject('MyClass')
)返回。MySQLifetch_object()
只会返回一个stdClass
对象。
有一件事要记住。
Mysqli 不支持 fetch_assoc() 函数,该函数将返回带有表示列名的键的列。当然可以编写你自己的函数来做到这一点,它甚至不是很长,但我真的很难写它(对于非信徒:如果你觉得这很容易,请自己尝试一下,不要'不要作弊 :) )