PDO 更适合多数据库支持与事务灵活性,MySQLi 更轻量但仅限 MySQL;应采用懒连接、强制预处理绑定参数,并提供错误信息接口而非盲目抛异常。

用 PDO 还是 MySQLi?先看项目兼容性需求
PHP 8.2+ 已移除 mysql_* 扩展,MySQLi 和 PDO 是唯二官方支持的方案。选哪个不取决于“谁更高级”,而取决于你是否需要多数据库支持或事务灵活性:
-
PDO支持 MySQL、PostgreSQL、SQLite、Oracle 等,只要换DSN字符串就能切库;但默认不模拟预处理(需显式设PDO::ATTR_EMULATE_PREPARES = false) -
MySQLi对 MySQL 优化更直接,面向对象接口简洁,但硬绑定 MySQL,无法平滑切换 - 若项目明确只用 MySQL 且无跨库计划,
MySQLi封装更轻量;若未来可能上 PostgreSQL 或要统一抽象层,PDO是唯一合理选择
构造方法里别直接连库,把连接延迟到第一次查询
很多封装类在 __construct() 就调用 new PDO() 或 mysqli_connect(),这会导致:哪怕只实例化、没执行任何 SQL,也建立了一次连接,浪费资源,还可能因配置错误提前崩掉。
正确做法是「懒连接」:
- 构造时只存配置数组,不建连接
- 首次调用
query()、insert()等方法时,再检查$this->pdo或$this->link是否为空,为空则初始化 - 这样能避免误初始化、方便单元测试 mock、也利于连接池或连接复用扩展
示例关键逻辑:
private $pdo;
private $config;
public function __construct(array $config) {
$this->config = $config;
}
private function connect() {
if ($this->pdo === null) {
$dsn = "mysql:host={$this->config['host']};dbname={$this->config['dbname']};charset={$this->config['charset']}";
$this->pdo = new PDO($dsn, $this->config['user'], $this->config['pass'], [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
}
}
参数绑定必须强制走 prepare + execute,别拼 SQL
封装类里最常被绕过的安全红线就是字符串拼接 SQL。比如写成 "WHERE id = {$id}" 或 "INSERT INTO user VALUES ('{$name}', '{$pwd}') —— 这等于给 SQL 注入开大门。
立即学习“PHP免费学习笔记(深入)”;
所有写操作(insert、update、delete)和带变量的读操作(where 条件),必须走预处理流程:
-
PDO:用prepare()+execute($params),键名用:name或?占位 -
MySQLi:用prepare()+bind_param(),注意类型字符(s/i/d)不能错 - 别图省事封装一个“万能 query”方法接受原始 SQL 字符串——那不是封装,是埋雷
例如 update() 方法内部应类似:
$sql = "UPDATE {$table} SET name = :name WHERE id = :id";
$stmt = $this->pdo->prepare($sql);
$stmt->execute(['name' => $data['name'], 'id' => $id]);
错误处理别只 throw Exception,得留出口给业务判断
封装类抛出 PDOException 或 mysqli_sql_exception 很常见,但问题在于:业务层往往只需要知道“失败了”,并不想 catch 异常再重新包装。更糟的是,有些类把错误吞掉、只返回 false,导致调用方无法区分是“查无结果”还是“连库失败”。
推荐双轨策略:
- 对外提供
lastError()和lastErrorCode()方法,返回最近一次操作的$e->getMessage()和$e->getCode() - 所有方法默认返回布尔值或结果集,失败时不 throw(除非显式开启严格模式)
- 加一个
setThrowOnError(bool $flag)开关,让使用者按需决定异常行为
这点容易被忽略:封装的价值不是“替你处理错误”,而是“让你能清晰地感知和响应错误”。



















