
本文详解为何使用 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 日期 线路 班次 起点 操作 暂无数据 ">编辑 " data-toggle="modal">删除
? 关键改进说明:
立即学习“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()); 查看底层错误详情。
遵循以上方案,你的表格不仅能正确显示数据,还将具备生产环境所需的健壮性与安全性。