4.0 KiB
4.0 KiB
Plan — DebugAgent: "Undefined array key 'id'" 调试计划
版本:v1.0 | 日期:2026-04-20 | Agent:council/DebugAgent
任务概述
调查 ShopXO 后台编辑票务商品(goods_id=118)保存时报错:
Undefined array key "id"
根因分析摘要(Round 1 快速结论)
1. 最可能触发点
AdminGoodsSaveHandle.php 第 71 行:
$template = Db::name('vr_seat_templates')->find($templateId);
$seatMap = json_decode($template['seat_map'] ?? '{}', true); // ← 危险
find()查不到记录时返回null??操作符只防御$template为null,不防御$template存在但键'seat_map'缺失- PHP 8+ 会报
Undefined array key "seat_map",而非 "id"
真正报 "id" 的位置——第 77 行 array_filter 回调内:
return in_array($r['id'], $config['selected_rooms'] ?? []);
// ^^^^^^ 如果 $r(room 对象)缺少 'id' 键则触发
但如果 room 数据正常(有 id),则第 71 行是实际断路点。
2. 表前缀问题(核心根因)
| 代码 | 表名方法 | 实际 SQL 表 |
|---|---|---|
BaseService::table('seat_templates') |
'vr_' + 'seat_templates' |
vr_seat_templates ✅ |
Db::name('vr_seat_templates') |
ThinkPHP Db::name() |
取决于 database.php 配置前缀 |
Db::name('Goods') |
ThinkPHP Db::name() |
sxo_goods ✅(ShopXO 系统表) |
ShopXO 数据库配置(需确认 shopxo/config/database.php):
- 若
prefix='sxo_':则Db::name('vr_seat_templates')→ 查表sxo_vr_seat_templates(不存在) - 若
prefix='vrt_':则Db::name('vr_seat_templates')→ 查表vrt_vr_seat_templates(不存在) - 正确表名应来自 ThinkPHP 原始前缀(ShopXO 插件表一般不带前缀或用独立前缀)
SeatSkuService 使用 BaseService::table() → vr_seat_templates(正确)
AdminGoodsSaveHandle 使用 Db::name('vr_seat_templates') → 可能查错表(错误)
3. 如果 find($templateId) 返回 null
第 71 行:$template['seat_map'] → Undefined array key 'seat_map'(不是 'id')
第 72 行:$allRooms = $seatMap['rooms'] ?? []; → 此行安全(?? 防御)
4. vr_goods_config JSON 解码
$configs = json_decode($rawConfig, true); // → array|null
if (is_array($configs) && !empty($configs)) { ... } // 防御正确
$configs 是数组时 $config['template_id'] 访问安全(不会触发 "id" 错误)。
5. selected_rooms 数据类型
selected_rooms:string[](room id 数组),e.g.["room_id_xxx"]$r['id']: 来自seat_map.rooms[].id,通常是字符串- 类型匹配:无类型强制问题,但若
room.id为null或缺失则触发 "id"
6. $data['item_type'] 访问安全
第 59 行:($data['item_type'] ?? '') === 'ticket' — 有 ?? 防御,安全。
任务清单(Round 2 执行)
- Task 1: 读取
shopxo/config/database.php,确认prefix配置值 - Task 2: 读取
AdminGoodsSaveHandle.php第 70-72 行,确认$template为 null 时实际报错信息 - Task 3: 确认 ShopXO
Db::name()表前缀行为(查 ShopXO 源码或文档) - Task 4: 编写根因报告
reports/DebugAgent-ROOT_CAUSE.md - Task 5: 给出修复建议(用
BaseService::table()替代Db::name())
阶段划分
| 阶段 | 内容 | 状态 |
|---|---|---|
| Draft | Round 1:代码静态分析,定位可疑行 | ✅ 完成 |
| Review | Round 2:读取配置文件确认表前缀,输出根因报告 | 待做 |
| Finalize | Round 3:合并报告到 main,提交调试结论 | 待做 |
依赖
- Task 1-3 必须按顺序执行(需读取配置文件)
- 不需要 BackendArchitect / SecurityEngineer 配合,可独立完成
执行顺序
Task 1 → Task 2 → Task 3(串行,每步确认后立即 commit)→ Task 4 → Task 5
声称
- [Claimed: council/DebugAgent] — Task 1-5 全部