mysqli_fetch_array() 默认返回数字键与字符串键并存的混合数组,内存占用高且易出错;mysqli_fetch_assoc() 仅返回字符串键关联数组,适合按字段名访问。

mysqli_fetch_array() 和 mysqli_fetch_assoc() 的区别必须分清
直接用 mysqli_fetch_array() 得到的是同时含数字键和字符串键的混合数组,内存占用翻倍,且容易在循环中因键名混淆出错。真正需要纯关联数组(比如用 $row['id'] 访问)时,必须用 mysqli_fetch_assoc()。
常见错误是查完就 var_dump() 看结构,发现有两套键就懵了——其实不是数据重复,是函数默认行为。如果明确只要字符串键,就别依赖默认参数:
-
mysqli_fetch_array($result, MYSQLI_ASSOC)等价于mysqli_fetch_assoc($result) -
mysqli_fetch_array($result, MYSQLI_NUM)只要数字键 - 不传第二个参数或传
MYSQLI_BOTH(默认),就是双键数组,慎用
PDO::fetch() 默认只返回关联数组,但 fetchAll() 有陷阱
PDO::fetch() 默认行为是 PDO::FETCH_ASSOC,这点比 mysqli 更友好;但很多人一上来就写 $pdo->query($sql)->fetchAll(),结果发现返回空数组——问题往往出在没检查 SQL 是否执行成功,或者没设置正确的 PDO 属性。
关键配置必须提前设好:
-
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION),否则错误静默失败 -
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC),避免后续每个fetch()都要重复写模式 -
fetchAll()返回二维数组,但若查询无结果,它返回空数组[],不是false,用empty()判断比=== false更安全
一次性取全部数据时,注意内存和游标状态
用 mysqli_fetch_all($result, MYSQLI_ASSOC) 或 PDO::fetchAll() 是最省事的方式,但前提是结果集不大。一旦查出几万行,PHP 进程内存可能直接爆掉,而且数据库连接会被一直占着,直到变量被销毁或脚本结束。
更稳妥的做法是边取边处理:
- 不用
fetch_all,改用循环 +fetch_assoc或fetch() - 确保循环内不累积大数组,比如不要写
$all[] = $row无限追加 - 查询完立刻
mysqli_free_result($result)或让 PDO Statement 自动释放(调用execute()后旧 statement 会自动清理) - 如果真要全取,先
mysqli_num_rows($result)或rowCount()估算大小,超阈值(如 5000 行)就抛异常或切分查询
从 MySQLi 面向对象写法迁移到 PDO 时最容易漏的点
很多老项目用 new mysqli(),转 PDO 时以为只是换类名,结果卡在 fetch 行为不一致上。最典型的是:MySQLi 的 fetch_array() 默认返回混合键,而 PDO 的 fetch() 默认只返回关联键——这会导致原来靠 $row[0] 取第一列的代码直接报 notice。
迁移时必须检查所有取值逻辑:
- 把
$row[0]改成$row['column_name'],或显式指定PDO::FETCH_NUM - 原 MySQLi 中用
mysqli_data_seek($result, 0)重置指针,PDO 没有等效方法,需重新execute()或缓存结果 - PDO 的预处理语句绑定参数后,
execute()返回布尔值,不能直接当结果集用,必须再调fetch()或fetchAll()
关联数组看似简单,但键名来源、内存生命周期、错误反馈方式这些细节,才是实际跑起来卡住的关键。别信“自动转数组”这种说法,每一步都要确认返回值类型和资源状态。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











