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 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 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, categories
  • tags → for articles, videos, photos
  • likes → 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 *_typeIndex 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.