多态关联表必须用 morphs('commentable') 创建 commentable_id(unsignedBigInteger)和 commentable_type(string(255)),并自动加联合索引;类名存储需通过 Relation::morphMap 配置短名映射,不可擅自修改字段名。

多态关联的数据表结构必须严格遵循 Laravel 的字段命名和类型约定,不能靠经验或猜测来建。
核心字段必须用默认名称和类型
以评论(comments)可属于文章、视频、用户等任意模型为例,其表中必须包含:
-
commentable_id:无符号大整型(
unsignedBigInteger),不能用id、bigIncrements或普通integer -
commentable_type:字符串类型(
string),长度至少 255(因完整类名如App\Models\Video可能很长)
用 morphs() 方法建表最安全
在迁移文件中直接调用:$table->morphs('commentable');
这一行自动完成四件事:
- 创建
commentable_id字段(unsignedBigInteger) - 创建
commentable_type字段(string(255)) - 添加联合索引
index(['commentable_id', 'commentable_type'])(避免 with 预加载时全表扫描) - 不加外键约束(这是 Laravel 故意设计,因目标模型不固定)
类名存储规则与 morphMap 配置
commentable_type 字段默认存的是完整类名,例如:App\Models\Post、App\Models\Video
如果你希望数据库里只存短名(如 post、video),必须提前注册映射:
- 在
AppServiceProvider::boot()中调用:Relation::morphMap(['post' => Post::class, 'video' => Video::class]); - 否则查询时会尝试加载
post类,报错Class 'post' not found
不要擅自改字段名
如果把字段写成 target_id 和 target_type,Laravel 默认无法识别。虽然可以手动覆盖:
$this->morphTo('target', 'target_id', 'target_type')- 但这样绕过了
morphs()的保障机制,也破坏团队协作规范,不推荐


















