PDO 使用 fetchAll(PDO::FETCH_ASSOC) 返回的是二维数组,外层数组每个元素本身仍是关联数组;直接 echo $value 会导致“Array to string conversion”错误,必须逐层解构——先遍历记录,再遍历每条记录的键值对。
不少开发者第一次接触 PDO 取值时,可能都遇到过这个情况:从数据库里拉了配置数据,明明看着数据拿到了,结果 echo 出来却报了个“Array to string conversion”的警告。问题是,这个警告到底在说什么?
关键在于,fetchAll(PDO::FETCH_ASSOC) 返回的结构,并不是一个一维的键值对映射,而是一个索引数组,里面的每个元素都是一个关联数组。举个例子,你执行 SELECT setting, setting_value FROM app_config,拿到的结果可能是这样的:[0] => ['setting' => 'site_title', 'setting_value' => 'My Website']。如果你直接用 foreach ($stmt as $key => $value) 然后 echo "$key = $value",PHP 自然会尝试把内层那个关联数组($value)转成字符串——结果就是报错。
所以,正确的做法其实很简单:用两层循环来结构。
- 外层循环负责遍历每一条查询结果记录(也就是每个关联子数组);
- 内层循环再遍历这一条记录里的所有键值对。
下面是完整、安全的示例代码:
query("SELECT setting, setting_value FROM app_config")->fetchAll(PDO::FETCH_ASSOC);
// ✅ 正确遍历:外层取记录,内层取字段键值
foreach ($stmt as $record) {
foreach ($record as $field => $val) {
echo "{$field}: " . htmlspecialchars($val) . "
";
}
}
这里有几个关键点需要留意:
- 别踩的坑: 直接
echo "$key = $value"是行不通的,$value 是个数组,不是字符串; - 另一个常见错误: 有人会写成
foreach ($key as $result),但 $key 是整数索引(0, 1, 2...),不是数组,根本没法遍历; - 命名建议: 用
$record或$row表示单条结果,用$field或$column表示字段名,语义更清晰; - 安全提示: 输出用户数据(比如
setting_value)时,一定要用htmlspecialchars()转义,防止 XSS 攻击; - 性能优化: 如果你的目标只是构建一个配置映射(比如
['site_title' => 'My Website']),可以一步到位:
$config = [];
foreach ($stmt as $row) {
$config[$row['setting']] = $row['setting_value'];
}
// 后续直接 $config['site_title'] 就完事了
说白了,这种二维关联数组的迭代逻辑,不只是配置表读取时能用,凡是涉及 PDO::FETCH_ASSOC 的场景——不管是用户列表、文章元数据,还是其他什么数据——都适用。这是 PHP 数据库开发里一个基础但非常实用的技能,掌握它,能帮你避免很多不必要的调试烦恼。