在PHP项目开发中,数据库查询是最基础也最核心的操作之一,而mysqli和PDO是PHP中两款主流的数据库操作扩展库,很多开发者在选型时都会纠结两者的差异。本文将从多个维度展开对比,帮助大家做出合适的选择。

mysqli与PDO基础概念
mysqli是MySQL Improved Extension的缩写,是专门为MySQL数据库设计的扩展,仅支持MySQL数据库,是早期mysql扩展的升级版本,修复了旧扩展的诸多安全问题,增加了面向对象的使用方式。
PDO是PHP Data Objects的缩写,是一个数据库访问抽象层,支持多种数据库,包括MySQL、PostgreSQL、SQLite、Oracle等,提供统一的API接口,切换数据库时无需修改大量业务代码。
核心差异对比
1. 数据库兼容性
这是两者最本质的区别,具体差异如下:
| 对比项 | mysqli | PDO |
|---|---|---|
| 支持数据库 | 仅支持MySQL | 支持MySQL、PostgreSQL、SQLite等多种数据库 |
| 切换数据库成本 | 极高,需重写所有数据库操作代码 | 极低,仅需修改连接参数,业务代码无需变动 |
2. 查询语句执行方式
两者都支持面向对象和面向过程两种使用风格,以下是执行简单查询的代码示例:
mysqli面向对象方式查询
<?php
// 建立数据库连接
$mysqli = new mysqli('127.0.0.1', 'root', 'password', 'test_db', 3306);
// 检查连接是否成功
if ($mysqli->connect_error) {
die('连接失败:' . $mysqli->connect_error);
}
// 执行查询语句
$sql = 'SELECT id, username FROM users WHERE age > 18';
$result = $mysqli->query($sql);
// 遍历查询结果
if ($result) {
while ($row = $result->fetch_assoc()) {
echo '用户ID:' . $row['id'] . ',用户名:' . $row['username'] . '<br/>';
}
// 释放结果集
$result->free();
}
// 关闭连接
$mysqli->close();
?>
PDO方式查询
<?php
// 建立数据库连接
try {
$pdo = new PDO('mysql:host=127.0.0.1;dbname=test_db;port=3306', 'root', 'password');
// 设置错误模式为异常
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die('连接失败:' . $e->getMessage());
}
// 执行查询语句
$sql = 'SELECT id, username FROM users WHERE age > 18';
$stmt = $pdo->query($sql);
// 遍历查询结果
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo '用户ID:' . $row['id'] . ',用户名:' . $row['username'] . '<br/>';
}
// 关闭连接,PDO无需显式关闭,脚本执行完自动释放
?>
3. 预处理语句支持
预处理语句是防止SQL注入的重要手段,两者都支持但实现方式不同:
mysqli预处理示例
<?php
$mysqli = new mysqli('127.0.0.1', 'root', 'password', 'test_db');
$sql = 'SELECT id, username FROM users WHERE age > ? AND status = ?';
// 准备预处理语句
$stmt = $mysqli->prepare($sql);
// 绑定参数,i代表整数,s代表字符串
$age = 18;
$status = 1;
$stmt->bind_param('ii', $age, $status);
// 执行语句
$stmt->execute();
// 绑定结果集
$stmt->bind_result($id, $username);
// 遍历结果
while ($stmt->fetch()) {
echo '用户ID:' . $id . ',用户名:' . $username . '<br/>';
}
$stmt->close();
$mysqli->close();
?>
PDO预处理示例
<?php
$pdo = new PDO('mysql:host=127.0.0.1;dbname=test_db', 'root', 'password');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = 'SELECT id, username FROM users WHERE age > :age AND status = :status';
// 准备预处理语句
$stmt = $pdo->prepare($sql);
// 绑定参数并执行
$stmt->execute([':age' => 18, ':status' => 1]);
// 获取结果
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($result as $row) {
echo '用户ID:' . $row['id'] . ',用户名:' . $row['username'] . '<br/>';
}
?>
可以看到PDO的预处理支持命名占位符,比mysqli的位置占位符可读性更强,参数绑定也更灵活。
4. 错误处理方式
mysqli默认不抛出异常,需要手动检查连接和查询的返回值判断错误,而PDO可以设置错误模式为异常,通过try-catch统一捕获错误,代码更简洁。
选型建议
- 如果项目仅使用MySQL数据库,且不需要考虑后续数据库迁移,可以选择mysqli,它的MySQL专属功能支持更完善,性能略优于PDO。
- 如果项目需要支持多种数据库,或者未来可能有数据库迁移的需求,优先选择PDO,统一的API可以大幅降低迁移成本。
- 如果是新项目,没有历史包袱,推荐使用PDO,它的预处理语法更友好,错误处理机制更完善,代码可维护性更高。
总结
mysqli和PDO都是成熟的PHP数据库扩展,没有绝对的好坏之分,核心差异在于数据库兼容性和使用习惯。开发者可以根据项目的数据库需求、团队技术栈选择合适的扩展,只要正确使用预处理语句,两者都能安全地完成数据库查询操作。