Laravel morphs() Explained — Complete Guide to Polymorphic Relationships in Laravel 

Learn how Laravel morphs() works with real examples, migrations, model relationships, database structure, and best practices for scalable applications. 

What is morphs() in Laravel? 

In Laravel, the morphs() method is used to create polymorphic relationships

It allows multiple models to share the same relationship table. 

For example: 

  • Posts can have comments  
  • Videos can have comments  
  • Products can have comments  

Instead of creating separate tables like: 

  • post_comments 
  • video_comments 
  • product_comments 

Laravel allows you to store everything in a single table: 

comments 

using polymorphic relationships. 

Laravel morphs() Syntax 

$table->morphs(‘commentable’); 

This automatically creates two database columns: 

  • commentable_id 
  • commentable_type 

What Does morphs() Create? 

Internally, Laravel creates: 

$table->unsignedBigInteger('commentable_id'); 
 
$table->string('commentable_type'); 
 
$table->index([ 
    'commentable_id', 
    'commentable_type' 
]); 

Why Use Polymorphic Relationships? 

Polymorphic relationships help you: 

✅ Reduce duplicate tables 
✅ Create reusable relationships 
✅ Build scalable applications 
✅ Keep database structure clean 
✅ Simplify application logic 

Real-World Example 

Imagine a blogging platform where: 

  • Posts can have comments  
  • Videos can also have comments  

Instead of creating multiple comment tables, Laravel stores: 

id message commentable_id commentable_type 
Nice article App\Models\Post 
Great video App\Models\Video 

Laravel identifies: 

  • Which model owns the comment  
  • Which record belongs to that model  

using: 

  • commentable_id  
  • commentable_type  

Creating Migration Using morphs() 

comments Migration 

Schema::create('comments', function (Blueprint $table) {  
    $table->id();  
    $table->text('message');  
    $table->morphs('commentable');  
    $table->timestamps();  
}); 

Database Table Structure 

Column Type 
id BIGINT 
message TEXT 
commentable_id BIGINT 
commentable_type VARCHAR 
created_at TIMESTAMP 
updated_at TIMESTAMP 

Laravel Model Relationships 

Post Model 

class Post extends Model 

    public function comments() 
    { 
        return $this->morphMany( 
            Comment::class, 
            'commentable' 
        ); 
    } 

Video Model 

class Video extends Model 

    public function comments() 
    { 
        return $this->morphMany( 
            Comment::class, 
            'commentable' 
        ); 
    } 

Comment Model 

class Comment extends Model 

    public function commentable() 
    { 
        return $this->morphTo(); 
    } 

Insert Data Example 

Add Comment to Post 

$post = Post::find(1);  
$post->comments()->create([ 
    'message' => 'Excellent tutorial' 
]); 

Laravel automatically stores: 

Column Value 
commentable_id 
commentable_type App\Models\Post 

Fetch Relationship Data 

Get All Comments of Post 

$post->comments; 

Get Parent Model from Comment 

$comment->commentable; 

Laravel automatically detects whether the comment belongs to: 

  • Post  
  • Video  
  • Product  
  • Any other model  

Types of Morph Methods in Laravel 

1. morphs() 

Creates standard BIGINT polymorphic keys. 

$table->morphs('imageable'); 

2. nullableMorphs() 

Creates nullable morph columns. 

$table->nullableMorphs('imageable'); 

3. uuidMorphs() 

Uses UUID instead of BIGINT. 

$table->uuidMorphs('imageable'); 

4. nullableUuidMorphs() 

Nullable UUID polymorphic relationship. 

$table->nullableUuidMorphs('imageable'); 

Common Use Cases of morphs() 

Feature Morph Name 
Comments commentable 
Images imageable 
Likes likeable 
Tags taggable 
Attachments attachable 

Visual Understanding of Laravel Polymorphic Relationships 

 

Traditional vs Polymorphic Structure 

Traditional Database Design 

  • posts 
  • videos 
  • post_comments 
  • video_comments 

Polymorphic Database Design 

  • posts 
    videos 
    comments 
  • Much cleaner and scalable. 

Performance Considerations 

Advantages 

✅ Reusable architecture 
✅ Fewer database tables 
✅ Easier maintenance 
✅ Flexible relationships 
✅ Better scalability 

Disadvantages 

❌ Slightly complex SQL queries 
❌ Reporting queries can be harder 
❌ Requires indexing for large datasets

 

Best Practices for Laravel morphs() 

1. Use Meaningful Morph Names 

Good: 

  • commentable 
  • imageable 
  • taggable 

Bad: 

  • data 
  • item 
  • object 

2. Use Morph Maps 

Instead of storing: 

App\Models\Post 

store shorter aliases. 

AppServiceProvider 

use Illuminate\Database\Eloquent\Relations\Relation; 
Relation::enforceMorphMap([ 
    'post' => Post::class, 
    'video' => Video::class, 
]); 

Now database stores: 

  • post 
  • video 

This improves: 

✅ Readability 
✅ Security 
✅ Database cleanliness 

Final Thoughts 

Laravel morphs() is one of the most powerful features for designing scalable and reusable database relationships. 

It helps developers avoid duplicate tables while keeping applications flexible and maintainable. 

If your application has shared features like: 

  • comments  
  • likes  
  • tags  
  • images  
  • attachments  

then polymorphic relationships are the perfect solution. 

Mastering Laravel polymorphic relationships will make your application architecture much cleaner and more professional. 

Frequently Asked Questions (FAQ) 

morphs() creates polymorphic relationship columns in Laravel migrations.

It creates: 

  • _id  
  • _type  

columns automatically. 

A polymorphic relationship allows multiple models to share one relationship table.

Use it when multiple models share common functionality like:

  • comments
  • images
  • likes
  • tags