council(draft): DebugAgent - plan.md: debug "Undefined array key id" error

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
council/ProductManager
Council 2026-04-20 09:46:20 +08:00
parent 98bd6a52cf
commit 0385f79106
1 changed files with 85 additions and 25 deletions

110
plan.md
View File

@ -1,54 +1,114 @@
# Plan — 文档评估 (Architect) # Plan — DebugAgent: "Undefined array key 'id'" 调试计划
> 版本v1.0 | 日期2026-04-20 | Agentcouncil/Architect > 版本v1.0 | 日期2026-04-20 | Agentcouncil/DebugAgent
--- ---
## 任务概述 ## 任务概述
对 vr-shopxo-plugin 项目三份文档进行评审: 调查 ShopXO 后台编辑票务商品goods_id=118保存时报错
1. `docs/14_TEMPLATE_RENDER_INVESTIGATION.md` ```
2. `docs/PHASE2_PLAN.md` Undefined array key "id"
3. `docs/DEVELOPMENT_LOG.md`(第十一、十二章) ```
评审维度:准确性、完整性、可操作性、一致性、误导风险。
**不读代码文件,只读文档。输出到 `reviews/` 目录。**
--- ---
## 任务清单 ## 根因分析摘要Round 1 快速结论)
- [x] **Task 1**: 评审 `docs/14_TEMPLATE_RENDER_INVESTIGATION.md``reviews/Architect-on-doc14.md` ### 1. 最可能触发点
- [Done: council/Architect]
- [x] **Task 2**: 评审 `docs/PHASE2_PLAN.md``reviews/Architect-on-PHASE2_PLAN.md` **AdminGoodsSaveHandle.php 第 71 行**
- [Done: council/Architect] ```php
$template = Db::name('vr_seat_templates')->find($templateId);
$seatMap = json_decode($template['seat_map'] ?? '{}', true); // ← 危险
```
- [x] **Task 3**: 评审 `docs/DEVELOPMENT_LOG.md`(第十一、十二章)→ `reviews/Architect-on-DEV_LOG.md` - `find()` 查不到记录时返回 `null`
- [Done: council/Architect] - `??` 操作符只防御 `$template``null`**不防御** `$template` 存在但键 `'seat_map'` 缺失
- PHP 8+ 会报 `Undefined array key "seat_map"`,而非 "id"
- [x] **Task 4**: 综合三份评审,输出 Top 3 修正建议 → `reviews/Architect-DOC-SUMMARY.md` **真正报 "id" 的位置**——第 77 行 `array_filter` 回调内:
- [Done: council/Architect] ```php
return in_array($r['id'], $config['selected_rooms'] ?? []);
// ^^^^^^ 如果 $rroom 对象)缺少 '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 解码
```php
$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** | ✅ Task 1-3逐份文档输出独立评审报告 | | **Draft** | Round 1代码静态分析定位可疑行 | ✅ 完成 |
| **Review** | ✅ Task 4综合汇总Top 3 修正建议 | | **Review** | Round 2读取配置文件确认表前缀输出根因报告 | 待做 |
| **Finalize** | ✅ 提交到 main标注完成 | | **Finalize** | Round 3合并报告到 main提交调试结论 | 待做 |
--- ---
## 依赖 ## 依赖
- 三份文档已读取完毕,无需额外探索 - Task 1-3 必须按顺序执行(需读取配置文件)
- 不需要 BackendArchitect / SecurityEngineer 配合,可独立完成 - 不需要 BackendArchitect / SecurityEngineer 配合,可独立完成
--- ---
## 执行顺序 ## 执行顺序
Task 1 → Task 2 → Task 3 → Task 4串行每份评审写完即 commit Task 1 → Task 2 → Task 3串行每步确认后立即 commit→ Task 4 → Task 5
---
## 声称
- [Claimed: council/DebugAgent] — Task 1-5 全部