Laravel Polymorphic Relationships – Complete Guide

Polymorphic relationships in Laravel allow a model to belong to more than one other model using a single association.
They are especially useful when multiple models share the same kind of relationship — such as comments, likes, tags, or images.
When to Use Polymorphic Relationships?
Use polymorphic relationships when:
- You have a single model (e.g.
Comment
) that can belong to multiple other models (e.g.Post
,Video
,Product
) - You don’t want to create separate foreign keys or tables for each relationship type.
Example Use Case: Comments on Posts and Videos
Let’s say you want to allow users to comment on both blog posts and videos.
Instead of creating two separate tables like post_comments
and video_comments
, you can create one comments
table using polymorphic relationships.
Step-by-Step Implementation
1. Create Models & Migrations
Run:
php artisan make:model Post -m php artisan make:model Video -m php artisan make:model Comment -m
2. Posts Table Migration (database/migrations/xxxx_create_posts_table.php
)
Schema::create('posts', function (Blueprint $table) { $table->id(); $table->string('title'); $table->timestamps(); });
3. Videos Table Migration
Schema::create('videos', function (Blueprint $table) { $table->id(); $table->string('title'); $table->timestamps(); });
4. Comments Table Migration
Schema::create('comments', function (Blueprint $table) { $table->id(); $table->text('body'); // Polymorphic relation fields $table->unsignedBigInteger('commentable_id'); $table->string('commentable_type'); $table->timestamps(); });
Here,commentable_id
andcommentable_type
determine the model (Post or Video) the comment belongs to.
5. Define Relationships in Models
In Comment.php
:
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Comment extends Model { protected $fillable = ['body']; public function commentable() { return $this->morphTo(); } }
In Post.php
:
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Post extends Model { protected $fillable = ['title']; public function comments() { return $this->morphMany(Comment::class, 'commentable'); } }
In Video.php
:
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Video extends Model { protected $fillable = ['title']; public function comments() { return $this->morphMany(Comment::class, 'commentable'); } }
6. Using the Relationship (Example)
Create Post and Add Comment:
$post = Post::create(['title' => 'Laravel Polymorphic Tutorial']); $post->comments()->create(['body' => 'Great article!']);
Create Video and Add Comment:
$video = Video::create(['title' => 'Laravel Video']); $video->comments()->create(['body' => 'Awesome tutorial!']);
7. Accessing Comments
Get all comments of a post:
$post = Post::find(1); foreach ($post->comments as $comment) { echo $comment->body; }
Get the parent of a comment:
$comment = Comment::find(1); $parent = $comment->commentable; // Could be Post or Video
Reverse: One Model with Many Parent Models
The power of polymorphic is that you can go both ways:
$post->comments
→ all comments for the post$comment->commentable
→ the post or video it belongs to
Real-Life Use Cases
comments
→ for posts, products, videos, etc.images
→ for users, posts, categoriestags
→ for articles, videos, photoslikes
→ for any content
Tips & Gotchas
TipDescriptionUse correct typecommentable_type
must store full class name (App\Models\Post
)morphTo()
magicLaravel auto-resolves based on *_id
and *_type
Index columnsAdd indexes on commentable_id
and commentable_type
for speedUse with()
Eager load relationships to reduce queries
Bonus: Migration Index Example
$table->index(['commentable_id', 'commentable_type']);
Summary
FeatureBenefitmorphTo()
Allows one model to belong to multiple typesmorphMany()
/ morphOne()
Used by the parent modelsReduces tablesClean design, less duplicationGood for shared behaviorsLike comments, tags, uploads
Conclusion
Laravel’s polymorphic relationships are a powerful way to manage shared relationships across multiple models. They save you from writing repetitive code and keep your database clean and efficient.
Comments (0)