瀏覽代碼

fix(game): 修复标签系统多态关联字段名错误

- 在 GameRewardGroup、GameConsumeGroup、GameConditionGroup 和 GameTag模型中修正了多态关联的字段名
- 更新了标签系统设计文档中的相关代码示例
- 通过指定正确的外键字段名,解决了数据库错误问题- 验证了修复后的功能正常工作,无数据库错误
notfff 7 月之前
父節點
當前提交
e3d6fbc686

+ 144 - 0
AiWork/202501/031500-修复标签系统多态关联字段名错误.md

@@ -0,0 +1,144 @@
+# 修复标签系统多态关联字段名错误
+
+**任务时间**: 2025年01月03日 15:00  
+**任务状态**: ✅ 已完成  
+**开发者**: AI Assistant  
+
+## 问题描述
+
+用户访问奖励组编辑页面 `http://kku_laravel.local.gd/admin/game-reward-groups/29/edit` 时出现数据库错误:
+
+```
+SQLSTATE[42S22]: Column not found: 1054 Unknown column 'kku_game_tag_relations.game_tag_id' in 'field list'
+```
+
+错误原因是Laravel的多态关联配置中,期望的字段名是 `game_tag_id`,但实际数据库表中的字段名是 `tag_id`。
+
+## 问题分析
+
+### 数据库表结构
+`kku_game_tag_relations` 表的实际字段结构:
+- `id` - 主键
+- `tag_id` - 标签ID(外键关联game_tags表)
+- `taggable_type` - 关联模型类型
+- `taggable_id` - 关联模型ID
+- `created_at` / `updated_at` - 时间戳
+
+### 多态关联配置问题
+在模型的 `morphToMany` 方法中,没有指定正确的外键名称,导致Laravel使用默认的命名规则生成了错误的字段名。
+
+## 修复方案
+
+### 修复的模型文件
+
+1. **GameRewardGroup.php** - 奖励组模型
+2. **GameConsumeGroup.php** - 消耗组模型  
+3. **GameConditionGroup.php** - 条件组模型
+4. **GameTag.php** - 标签模型
+
+### 修复内容
+
+#### 1. 修复正向关联(组模型 -> 标签)
+
+**修复前:**
+```php
+public function tags()
+{
+    return $this->morphToMany(GameTag::class, 'taggable', 'game_tag_relations');
+}
+```
+
+**修复后:**
+```php
+public function tags()
+{
+    return $this->morphToMany(GameTag::class, 'taggable', 'game_tag_relations', 'taggable_id', 'tag_id');
+}
+```
+
+#### 2. 修复反向关联(标签 -> 组模型)
+
+**修复前:**
+```php
+public function rewardGroups()
+{
+    return $this->morphedByMany(GameRewardGroup::class, 'taggable', 'game_tag_relations');
+}
+```
+
+**修复后:**
+```php
+public function rewardGroups()
+{
+    return $this->morphedByMany(GameRewardGroup::class, 'taggable', 'game_tag_relations', 'tag_id', 'taggable_id');
+}
+```
+
+## 技术细节
+
+### morphToMany 方法参数说明
+```php
+morphToMany($related, $name, $table, $foreignPivotKey, $relatedPivotKey)
+```
+
+- `$related`: 关联的模型类
+- `$name`: 多态关联的名称前缀
+- `$table`: 中间表名称
+- `$foreignPivotKey`: 当前模型在中间表中的外键
+- `$relatedPivotKey`: 关联模型在中间表中的外键
+
+### morphedByMany 方法参数说明
+```php
+morphedByMany($related, $name, $table, $foreignPivotKey, $relatedPivotKey)
+```
+
+参数含义与 `morphToMany` 相同,但是外键的角色相反。
+
+## 修复验证
+
+### 测试页面
+1. ✅ 奖励组编辑页面:`http://kku_laravel.local.gd/admin/game-reward-groups/29/edit`
+2. ✅ 消耗组列表页面:`http://kku_laravel.local.gd/admin/game-consume-groups`
+3. ✅ 条件组列表页面:`http://kku_laravel.local.gd/admin/game-condition-groups`
+
+### 验证结果
+- 所有页面正常加载,无数据库错误
+- 标签功能正常工作,可以显示和选择标签
+- 多态关联查询正常执行
+
+## 影响范围
+
+### 修复的文件
+- `app/Module/Game/Models/GameRewardGroup.php`
+- `app/Module/Game/Models/GameConsumeGroup.php`
+- `app/Module/Game/Models/GameConditionGroup.php`
+- `app/Module/Game/Models/GameTag.php`
+- `app/Module/Game/Docs/标签系统设计.md`
+
+### 功能影响
+- 奖励组、消耗组、条件组的标签功能恢复正常
+- 后台管理页面的标签显示和筛选功能正常
+- 标签关联数据的查询和显示正常
+
+## 经验总结
+
+1. **多态关联配置要点**:
+   - 必须明确指定中间表的外键字段名
+   - 注意正向和反向关联的外键顺序
+   - 确保字段名与数据库表结构一致
+
+2. **调试方法**:
+   - 查看数据库错误信息中的字段名
+   - 对比实际表结构与Laravel期望的字段名
+   - 检查多态关联的参数配置
+
+3. **预防措施**:
+   - 在设计多态关联时,明确定义所有参数
+   - 编写单元测试验证关联关系
+   - 定期检查数据库查询日志
+
+## 后续建议
+
+1. **测试完善**:为标签系统编写完整的单元测试
+2. **文档更新**:更新相关技术文档,说明正确的多态关联配置
+3. **代码审查**:检查其他模型是否存在类似问题

+ 1 - 1
app/Module/Game/Docs/标签系统设计.md

@@ -48,7 +48,7 @@
 ```php
 public function tags()
 {
-    return $this->morphToMany(GameTag::class, 'taggable', 'game_tag_relations');
+    return $this->morphToMany(GameTag::class, 'taggable', 'game_tag_relations', 'taggable_id', 'tag_id');
 }
 ```
 

+ 1 - 1
app/Module/Game/Models/GameConditionGroup.php

@@ -86,7 +86,7 @@ class GameConditionGroup extends ModelCore
      */
     public function tags()
     {
-        return $this->morphToMany(GameTag::class, 'taggable', 'game_tag_relations');
+        return $this->morphToMany(GameTag::class, 'taggable', 'game_tag_relations', 'taggable_id', 'tag_id');
     }
 
     /**

+ 1 - 1
app/Module/Game/Models/GameConsumeGroup.php

@@ -54,7 +54,7 @@ class GameConsumeGroup extends ModelCore
      */
     public function tags()
     {
-        return $this->morphToMany(GameTag::class, 'taggable', 'game_tag_relations');
+        return $this->morphToMany(GameTag::class, 'taggable', 'game_tag_relations', 'taggable_id', 'tag_id');
     }
 
     /**

+ 1 - 1
app/Module/Game/Models/GameRewardGroup.php

@@ -69,7 +69,7 @@ class GameRewardGroup extends ModelCore
      */
     public function tags()
     {
-        return $this->morphToMany(GameTag::class, 'taggable', 'game_tag_relations');
+        return $this->morphToMany(GameTag::class, 'taggable', 'game_tag_relations', 'taggable_id', 'tag_id');
     }
 
     /**

+ 3 - 3
app/Module/Game/Models/GameTag.php

@@ -68,7 +68,7 @@ class GameTag extends ModelCore
      */
     public function rewardGroups()
     {
-        return $this->morphedByMany(GameRewardGroup::class, 'taggable', 'game_tag_relations');
+        return $this->morphedByMany(GameRewardGroup::class, 'taggable', 'game_tag_relations', 'tag_id', 'taggable_id');
     }
 
     /**
@@ -78,7 +78,7 @@ class GameTag extends ModelCore
      */
     public function consumeGroups()
     {
-        return $this->morphedByMany(GameConsumeGroup::class, 'taggable', 'game_tag_relations');
+        return $this->morphedByMany(GameConsumeGroup::class, 'taggable', 'game_tag_relations', 'tag_id', 'taggable_id');
     }
 
     /**
@@ -88,7 +88,7 @@ class GameTag extends ModelCore
      */
     public function conditionGroups()
     {
-        return $this->morphedByMany(GameConditionGroup::class, 'taggable', 'game_tag_relations');
+        return $this->morphedByMany(GameConditionGroup::class, 'taggable', 'game_tag_relations', 'tag_id', 'taggable_id');
     }
 
     /**