新手应优先学 PDO,因其强制关注 SQL 注入防护、异常处理与预处理等核心安全问题;需手动启用 PDO::ERRMODE_EXCEPTION 和 PDO::FETCH_ASSOC 才能获得健壮体验。

新手该优先学 PDO 还是 mysqli
直接说结论:新手应该从 PDO 入手,但不是因为它“更高级”,而是它强制你面对 SQL 注入、错误处理、预处理这些真正影响安全和稳定的核心问题。而 mysqli(尤其是面向过程写法)容易让新手写出看似能跑、实则脆弱的代码。
PDO 的默认行为会掩盖错误,必须手动开启异常模式
刚连上数据库时,PDO 默认静默失败——new PDO(...) 即使用户名密码错、库不存在,也不会报错,后续执行 query() 才崩。这对新手极不友好。
正确做法是创建实例时传入选项:
try {
$pdo = new PDO('mysql:host=localhost;dbname=test', $user, $pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
} catch (PDOException $e) {
die('连接失败: ' . $e->getMessage());
}-
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION是关键,否则所有错误都得手动检查$pdo->errorInfo() -
PDO::ATTR_DEFAULT_FETCH_MODE设为PDO::FETCH_ASSOC,避免返回数字索引数组导致字段顺序依赖 - 不推荐用
PDO::ATTR_EMULATE_PREPARES => false(默认已是false),除非你明确要关掉模拟预处理
mysqli 面向过程写法会让新手跳过错误检查
比如这样一段典型新手代码:
立即学习“PHP免费学习笔记(深入)”;
$conn = mysqli_connect('localhost', 'user', 'pass', 'test');
$result = mysqli_query($conn, "SELECT * FROM users WHERE id = $_GET[id]");问题一堆:mysqli_connect 失败没判断;$_GET[id] 直接拼进 SQL;没检查 mysqli_query 返回值是否为 false。
即使改用面向对象写法,也常漏掉错误检查:
$mysqli = new mysqli('localhost', 'user', 'pass', 'test');
// 忘了 if ($mysqli->connect_error) die(...),程序直接 fatal error-
mysqli的错误默认是警告级(E_WARNING),不中断执行,新手根本看不到 - 预处理写法比
PDO略啰嗦:$stmt = $mysqli->prepare("SELECT * FROM u WHERE id = ?")→bind_param()→execute()→get_result() - 不支持 PostgreSQL、SQLite 等其他数据库,换库就得重写所有数据层
实际项目里,PDO 的预处理写法更贴近现代开发习惯
比如带参数的查询,PDO 一行占位符搞定:
$stmt = $pdo->prepare("SELECT name, email FROM users WHERE status = ? AND created_at > ?");
$stmt->execute(['active', '2024-01-01']);
$users = $stmt->fetchAll();而 mysqli 要分三步绑定类型、值、再执行:
$stmt = $mysqli->prepare("SELECT name, email FROM users WHERE status = ? AND created_at > ?");
$stmt->bind_param('ss', $status, $date);
$status = 'active';
$date = '2024-01-01';
$stmt->execute();-
PDO支持命名参数(:status),可读性更强;mysqli只支持问号位置参数 -
PDO的fetch()/fetchAll()返回结构统一;mysqli的fetch_assoc()/fetch_array()容易混淆 - 很多现代框架(Laravel、Symfony)底层用的就是
PDO,早熟悉少踩迁移坑
真正容易被忽略的是:无论选哪个,都要立刻关掉 display_errors,打开 log_errors,别让数据库错误信息直接吐给用户。连不上数据库本身不是问题,暴露账号密码或表结构才是。











