
本文详解为何使用 pdo `prepare()` + `execute()` 后调用 `fetch()` 会返回布尔值而非数组,导致“trying to access array offset on value of type bool”错误,并提供安全、可维护的解决方案。
你遇到的错误——PHP Warning: Trying to access array offset on value of type bool——根本原因在于混淆了 PDO 的两种查询模式:你使用的是预处理语句(prepare() + execute()),却错误地期望 fetch() 直接返回关联数组;但实际上,PDOStatement::fetch() 在成功时返回数据行(数组),在无更多结果时返回 false。而你的循环 for($i=0; $row = $result->fetch(); $i++) 会在第一次 fetch() 返回 false(即没有数据或执行失败)时,立即将 $row 设为 false,后续所有 $row['id'] 等访问都会触发该警告。
更关键的是:$result->execute() 本身只返回布尔值(执行是否成功),它并不“产出”结果集;真正的数据需通过 $result->fetch() 或 $result->fetchAll() 获取。但前提是 SQL 执行成功且有数据返回。若数据库连接异常、表名错误、权限不足或查询无结果,fetch() 就会立即返回 false,进而引发连锁报错。
✅ 正确做法是:保持预处理的安全优势,同时正确获取数据。以下是推荐的健壮写法:
prepare("SELECT id, date, line, block, start FROM bustracker ORDER BY id ASC");
$stmt->execute();
// 使用 fetchAll() 一次性获取全部结果(更清晰,避免 while 循环嵌套 HTML 的可读性问题)
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
error_log("Database query failed: " . $e->getMessage());
die("数据加载失败,请稍后重试。");
}
?>
| ID | 日期 | 线路 | 班次 | 起点 | 操作 |
|---|---|---|---|---|---|
| 暂无数据 | |||||
| 编辑 删除 | |||||
? 关键改进说明:
采用 php+mysql 数据库方式运行的强大网上商店系统,执行效率高速度快,支持多语言,模板和代码分离,轻松创建属于自己的个性化用户界面 v3.5更新: 1).进一步静态化了活动商品. 2).提供了一些重要UFT-8转换文件 3).修复了除了网银在线支付其它支付显示错误的问题. 4).修改了LOGO广告管理,增加LOGO链接后主页LOGO路径错误的问题 5).修改了公告无法发布的问题,可能是打压
立即学习“PHP免费学习笔记(深入)”;
- ✅ 保留预处理(prepare + execute):防止 SQL 注入,比 query() 更安全;
- ✅ 显式捕获异常:try/catch 确保数据库错误不会暴露敏感信息;
- ✅ 使用 fetchAll(PDO::FETCH_ASSOC):返回关联数组,语义清晰,避免 while 循环中 $row 突然变为 false 的陷阱;
- ✅ 输出前转义内容:htmlspecialchars() 防止 XSS 攻击;
- ✅ URL 参数安全编码:urlencode() 处理特殊字符(如空格、中文 ID);
- ✅ 空数据友好提示:提升用户体验与调试效率。
⚠️ 注意事项:
- 检查 db.php 中 $conn 是否已正确配置为 PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC(可选,但推荐);
- 确认数据库表 bustracker 存在,且字段名 id, date, line, block, start 拼写完全一致(区分大小写取决于数据库配置);
- 若仍报错,请临时在 db.php 后添加 var_dump($stmt->errorInfo()); 查看底层错误详情。
遵循以上方案,你的表格不仅能正确显示数据,还将具备生产环境所需的健壮性与安全性。










