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_typemust store full class name (App\Models\Post)morphTo()magicLaravel auto-resolves based on*_idand*_typeIndex columnsAdd indexes oncommentable_idandcommentable_typefor 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)