fetch() 默认返回 PDO::FETCH_BOTH 类型,即同时包含数字索引和关联键的混合数组;但若未显式设置 PDO::ATTR_DEFAULT_FETCH_MODE,则实际默认值为 PDO::FETCH_BOTH,而非 PDO::FETCH_NUM。

fetch() 默认返回什么类型?
PDO 的 fetch() 默认返回的是数字索引数组(PDO::FETCH_NUM),不是关联数组。如果你直接写 $row = $stmt->fetch(); 却按 $row['name'] 访问,会报 Undefined index 错误。
要得到关联数组,必须显式指定取值模式:
-
$row = $stmt->fetch(PDO::FETCH_ASSOC);—— 只有字段名键(推荐) -
$row = $stmt->fetch(PDO::FETCH_BOTH);—— 同时含数字和字符串键(冗余,不建议) - 也可以在预处理时统一设置:
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
fetchAll() 怎么批量转关联数组?
fetchAll() 和 fetch() 一样,默认也是数字索引。常见错误是调用后直接 foreach ($rows as $r) echo $r['id']; 却没指定模式,导致报错。
正确写法:
立即学习“PHP免费学习笔记(深入)”;
-
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);—— 最常用,返回二维关联数组 -
$rows = $stmt->fetchAll(PDO::FETCH_GROUP | PDO::FETCH_ASSOC);—— 按首列分组(如需按分类聚合) - 如果已设过
ATTR_DEFAULT_FETCH_MODE,fetchAll()也会继承该模式
为什么用 PDO::FETCH_ASSOC 而不是 PDO::FETCH_OBJ?
两者都能通过字段名访问,但行为差异明显:
-
PDO::FETCH_ASSOC返回array,支持isset()、array_key_exists()、foreach等原生数组操作 -
PDO::FETCH_OBJ返回stdClass对象,字段是公开属性,但无法用isset($obj->field)安全判断(未赋值字段会触发 Notice) - 对象方式不支持
json_encode()时自动忽略 null 属性等控制,而数组更可控
除非你明确需要对象语义(比如配合某些 ORM 或魔术方法),否则关联数组更稳妥。
fetchColumn() 和 fetchAll(PDO::FETCH_COLUMN) 会受影响吗?
不会。fetchColumn() 总是返回单个标量值(如字符串、整数),和 fetch 模式无关;fetchAll(PDO::FETCH_COLUMN) 返回一维数值数组,也不走关联逻辑。
它们属于「降维」操作,和字段名映射无关。别试图对它们加 PDO::FETCH_ASSOC —— 这样做 PHP 会静默忽略或报错(取决于版本)。
真正容易被忽略的是:PDO 默认 fetch 模式是全局的,一旦在连接后设置了 ATTR_DEFAULT_FETCH_MODE,所有后续 fetch/fetchAll 都受其影响,包括第三方库内部调用 —— 如果你没意识到这点,调试时可能发现“明明没设,怎么突然变成关联数组了”。



















