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 VideosLet’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 & MigrationsRun:
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 MigrationSchema::create('videos', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->timestamps();
});
4. Comments Table MigrationSchema::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
and commentable_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 ModelsThe 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, categories-tags
→ for articles, videos, photos-likes
→ for any content## Tips & GotchasTipDescriptionUse correct typecommentable_type
must store full class name (App\Models\Post
)morphTo()
magicLaravel auto-resolves based on*_id
and*_type
Index columnsAdd indexes oncommentable_id
andcommentable_type
for speedUsewith()
Eager load relationships to reduce queries
Bonus: Migration Index Example$table->index(['commentable_id', 'commentable_type']);
SummaryFeatureBenefitmorphTo()
Allows one model to belong to multiple typesmorphMany()
/ morphOne()
Used by the parent modelsReduces tablesClean design, less duplicationGood for shared behaviorsLike comments, tags, uploads
**
Top comments (0)