Laravel 12 Polymorphic Relationships: The Ultimate Guide

Author

Kritim Yantra

Apr 06, 2025

Laravel 12 Polymorphic Relationships: The Ultimate Guide

Introduction to Polymorphic Relationships

Polymorphic relationships allow a model to belong to multiple other models on a single association. This powerful feature lets you create flexible database structures where one model can belong to various models without needing separate tables for each relationship.

Real-World Use Cases

  • Comment system: Comments can belong to Posts, Videos, or Products
  • Media attachments: Files can be attached to multiple models
  • Activity feeds: Activities can track actions on different models

Types of Polymorphic Relationships

Laravel supports three polymorphic relationship types:

  1. One-to-One Polymorphic
  2. One-to-Many Polymorphic
  3. Many-to-Many Polymorphic

1. One-to-Many Polymorphic Relationship

Example Scenario: Comments System

Comments can belong to either Posts or Videos.

Database Structure

comments
  id - integer
  body - text
  commentable_id - integer
  commentable_type - string

posts
  id - integer
  title - string
  body - text

videos
  id - integer
  title - string
  url - string

Migrations

// Create comments table
Schema::create('comments', function (Blueprint $table) {
    $table->id();
    $table->text('body');
    $table->unsignedBigInteger('commentable_id');
    $table->string('commentable_type');
    $table->timestamps();
});

Model Setup

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

// 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');
    }
}

Using the Relationship

// Create comment for a post
$post = Post::find(1);
$comment = $post->comments()->create([
    'body' => 'Great post!'
]);

// Create comment for a video
$video = Video::find(1);
$comment = $video->comments()->create([
    'body' => 'Nice video!'
]);

// Retrieve comments
$post = Post::with('comments')->find(1);
foreach ($post->comments as $comment) {
    echo $comment->body;
}

2. Many-to-Many Polymorphic Relationship

Example Scenario: Taggable System

Tags can be applied to Posts, Videos, and Products.

Database Structure

tags
  id - integer
  name - string

taggables
  tag_id - integer
  taggable_id - integer
  taggable_type - string

Migrations

Schema::create('taggables', function (Blueprint $table) {
    $table->unsignedBigInteger('tag_id');
    $table->unsignedBigInteger('taggable_id');
    $table->string('taggable_type');
});

Model Setup

// Tag.php
class Tag extends Model
{
    public function posts()
    {
        return $this->morphedByMany(Post::class, 'taggable');
    }

    public function videos()
    {
        return $this->morphedByMany(Video::class, 'taggable');
    }
}

// Post.php
class Post extends Model
{
    public function tags()
    {
        return $this->morphToMany(Tag::class, 'taggable');
    }
}

// Video.php
class Video extends Model
{
    public function tags()
    {
        return $this->morphToMany(Tag::class, 'taggable');
    }
}

Using the Relationship

// Attach tags to a post
$post = Post::find(1);
$post->tags()->attach([1, 2, 3]);

// Attach tags to a video
$video = Video::find(1);
$video->tags()->attach([2, 4]);

// Get all tags for a post
$post = Post::with('tags')->find(1);
foreach ($post->tags as $tag) {
    echo $tag->name;
}

// Find all posts with a specific tag
$tag = Tag::find(1);
$posts = $tag->posts;

3. One-to-One Polymorphic Relationship

Example Scenario: Image Attachments

Images can belong to either Users or Posts.

Database Structure

images
  id - integer
  url - string
  imageable_id - integer
  imageable_type - string

Model Setup

// Image.php
class Image extends Model
{
    public function imageable()
    {
        return $this->morphTo();
    }
}

// User.php
class User extends Model
{
    public function image()
    {
        return $this->morphOne(Image::class, 'imageable');
    }
}

// Post.php
class Post extends Model
{
    public function image()
    {
        return $this->morphOne(Image::class, 'imageable');
    }
}

Using the Relationship

// Create image for a user
$user = User::find(1);
$user->image()->create(['url' => 'users/1.jpg']);

// Create image for a post
$post = Post::find(1);
$post->image()->create(['url' => 'posts/1.jpg']);

// Retrieve image
$user = User::with('image')->find(1);
echo $user->image->url;

Advanced Polymorphic Techniques

1. Custom Polymorphic Types

By default, Laravel 12 stores the fully-qualified class name. You can customize this:

use Illuminate\Database\Eloquent\Relations\Relation;

Relation::morphMap([
    'post' => 'App\Models\Post',
    'video' => 'App\Models\Video',
]);

2. Eager Loading Polymorphic Relationships

// Eager load comments with their commentable models
$comments = Comment::with('commentable')->get();

foreach ($comments as $comment) {
    if ($comment->commentable instanceof Post) {
        // Handle post comment
    } elseif ($comment->commentable instanceof Video) {
        // Handle video comment
    }
}

3. Querying Polymorphic Relationships

// Get all comments for posts
$comments = Comment::where('commentable_type', 'App\Models\Post')->get();

// Get all tags assigned to videos
$tags = Tag::whereHas('videos')->get();

Conclusion

Polymorphic relationships in Laravel 12 provide incredible flexibility when you need models to associate with multiple other models. Key takeaways:

One-to-Many Polymorphic: For comment-like systems
Many-to-Many Polymorphic: For tagging systems
One-to-One Polymorphic: For single attachments
Customize with morph maps and advanced querying

📌 Questions? Drop them in the comments below!

Tags

Laravel Php

Comments

No comments yet. Be the first to comment!

Please log in to post a comment:

Sign in with Google

Related Posts

What Are Laravel 12 Service Providers?
Web Development
What Are Laravel 12 Service Providers?
Laravel Vue
Kritim Yantra Kritim Yantra
Mar 02, 2025
Laravel 12 & Vue3 Integration: How to Build API Calls for Dynamic Output
Kritim Yantra Kritim Yantra
Mar 13, 2025
Understanding Facades in Laravel 12: How to Create Custom Facades
Kritim Yantra Kritim Yantra
Mar 16, 2025