Kritim Yantra
Apr 06, 2025
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.
Laravel supports three polymorphic relationship types:
Comments can belong to either Posts or Videos.
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
// Create comments table
Schema::create('comments', function (Blueprint $table) {
$table->id();
$table->text('body');
$table->unsignedBigInteger('commentable_id');
$table->string('commentable_type');
$table->timestamps();
});
// 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');
}
}
// 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;
}
Tags can be applied to Posts, Videos, and Products.
tags
id - integer
name - string
taggables
tag_id - integer
taggable_id - integer
taggable_type - string
Schema::create('taggables', function (Blueprint $table) {
$table->unsignedBigInteger('tag_id');
$table->unsignedBigInteger('taggable_id');
$table->string('taggable_type');
});
// 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');
}
}
// 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;
Images can belong to either Users or Posts.
images
id - integer
url - string
imageable_id - integer
imageable_type - string
// 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');
}
}
// 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;
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',
]);
// 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
}
}
// 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();
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!
No comments yet. Be the first to comment!
Please log in to post a comment:
Sign in with Google