The morphTo relationship is used in polymorphic relationships to define the inverse side, where a model can belong to multiple different model types.

Real-World Examples

  • A Comment belongs to either a Post or a Video
  • An Image belongs to either a User or a Product
  • A Review belongs to either a Course or a Book

1.When to Use morphTo

Use morphTo when:

  • A child model can belong to different parent models
  • You want one table instead of many
  • The parent model type is dynamic

2.Example Scenario (Comments System)

Post   ─┐
├── Comment
Video  ─┘

✔ One comments table
✔ Multiple parent models

3.Database Structure

posts table

id
title

videos table

id
title

comments table

id
commentable_id
commentable_type
content
created_at

📌 commentable_id → parent ID
📌 commentable_type → parent model class

4.Create Models & Migrations

php artisan make:model Comment -m
php artisan make:model Post -m
php artisan make:model Video -m

comments migration

Schema::create('comments', function (Blueprint $table) {
$table->id();
$table->morphs('commentable'); // commentable_id & commentable_type
$table->text('content');
$table->timestamps();
});

Run:

php artisan migrate

5.Define morphTo in Child Model

Comment.php

class Comment extends Model
{
public function commentable()
{
return $this->morphTo();
}
}

✔ This allows Laravel to determine the parent dynamically.

6.Define Parent Relationships

Post.php

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

Video.php

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

7.Creating Polymorphic Records

Add comment to post

$post = Post::find(1);

$post->comments()->create([
'content' => 'Great post!'
]);

Add comment to video

$video = Video::find(1);

$video->comments()->create([
'content' => 'Nice video!'
]);

✔ Laravel automatically fills:

  • commentable_id
  • commentable_type

8.Fetch Parent Model Using morphTo

$comment = Comment::find(1);
$parent = $comment->commentable;

Determine Parent Type

if ($comment->commentable instanceof Post) {
echo 'This comment belongs to a post';
}

9. Eager Loading morphTo (IMPORTANT)

Wrong way

$comments = Comment::all();

foreach ($comments as $comment) {
$comment->commentable;
}

Correct way

$comments = Comment::with('commentable')->get();

10.Using morphTo with Image Example

Image.php

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

Access Parent

$image = Image::find(1);
$image->imageable;

11. Rename Morph Type (morphMap)

AppServiceProvider.php

use Illuminate\Database\Eloquent\Relations\Relation;

public function boot()
{
Relation::morphMap([
'post' => Post::class,
'video' => Video::class,
]);
}

Stored in DB:

commentable_type = post

✔ Shorter
✔ Safer
✔ Cleaner

12. Conditional Queries on morphTo

Comment::whereHasMorph(
'commentable',
[Post::class],
function ($query) {
$query->where('status', 'published');
}
)->get();

13.Real LMS Example (Reviews)

Course ─┐
        ├── Review
Book   ─┘

Review.php

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

Categorized in:

Laravel,