Polymorphic relationship cho một model thuộc về nhiều loại model cha qua một quan hệ duy nhất. Bảng con giữ hai cột: _id (khoá cha) và _type (tên class cha).
Tình huống kinh điển: comments gắn được vào cả Post lẫn Video; images, likes, activity_logs cũng vậy.
// comments: id, body, commentable_id, commentable_type
class Comment extends Model
{
public function commentable(): MorphTo { return $this->morphTo(); }
}
class Post extends Model
{
public function comments(): MorphMany { return $this->morphMany(Comment::class, 'commentable'); }
}Eager load một-nhiều-kiểu dùng morphWith để không sinh N+1 theo từng loại cha:
Comment::with(['commentable' => fn (MorphTo $m) => $m->morphWith([Post::class => ['author'], Video::class => []])])->get();Nhược điểm phải nói được:
- Không đặt được foreign key constraint ở tầng DB → mất ràng buộc toàn vẹn, dễ còn bản ghi mồ côi khi xoá cha.
- Cột *_type lưu tên class đầy đủ; đổi namespace là hỏng dữ liệu. Khắc phục bằng Relation::enforceMorphMap(['post' => Post::class, ...]) để lưu alias ngắn, ổn định.
- Query lọc theo loại cha kém hiệu quả hơn bảng riêng; cần index composite (commentable_type, commentable_id).