PHP
Implementing Laravel Eloquent Polymorphic One-to-Many Relationships
Connect a single model to multiple other models using a polymorphic one-to-many relationship in Laravel Eloquent, ideal for versatile associations like comments or notifications.
// In App\Models\Comment.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;
class Comment extends Model
{
protected $fillable = ['body'];
/**
* Get the parent model (post or video) that owns the comment.
*/
public function commentable(): MorphTo
{
return $this->morphTo();
}
}
// In App\Models\Post.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;
class Post extends Model
{
protected $fillable = ['title', 'body'];
/**
* Get all of the post's comments.
*/
public function comments(): MorphMany
{
return $this->morphMany(Comment::class, 'commentable');
}
}
// In App\Models\Video.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;
class Video extends Model
{
protected $fillable = ['title', 'url'];
/**
* Get all of the video's comments.
*/
public function comments(): MorphMany
{
return $this->morphMany(Comment::class, 'commentable');
}
}
// Usage example
use App\Models\Post;
use App\Models\Video;
use App\Models\Comment;
// Create a post and a video
$post = Post::create(['title' => 'My First Post', 'body' => 'Content of the post.']);
$video = Video::create(['title' => 'Laravel Tutorial', 'url' => 'https://example.com/video']);
// Add comments to the post
$post->comments()->create(['body' => 'Great post!']);
$post->comments()->create(['body' => 'Very informative.']);
// Add comments to the video
$video->comments()->create(['body' => 'Awesome video!']);
$video->comments()->create(['body' => 'Helped me a lot.']);
// Retrieve comments for the post
$postComments = $post->comments;
echo "Comments for Post '{$post->title}':
";
foreach ($postComments as $comment) {
echo "- {$comment->body}
";
}
// Retrieve comments for the video
$videoComments = $video->comments;
echo "
Comments for Video '{$video->title}':
";
foreach ($videoComments as $comment) {
echo "- {$comment->body}
";
}
// Retrieve a comment and its parent
$firstComment = Comment::first();
if ($firstComment) {
echo "
First comment body: {$firstComment->body}
";
echo "It belongs to type: " . $firstComment->commentable_type . " with ID: " . $firstComment->commentable_id . "
";
echo "Parent Title: " . $firstComment->commentable->title . "
";
}
// Database migration structure (example for 'comments' table)
// Schema::create('comments', function (Blueprint $table) {
// $table->id();
// $table->text('body');
// $table->morphs('commentable'); // Adds commentable_id (INT) and commentable_type (VARCHAR)
// $table->timestamps();
// });
How it works: Polymorphic relationships in Laravel Eloquent allow a model to belong to more than one other model on a single association. This snippet demonstrates a one-to-many polymorphic relationship where a `Comment` model can belong to either a `Post` or a `Video` model. The `Comment` model defines a `commentable()` method using `morphTo()`, and both `Post` and `Video` models define a `comments()` method using `morphMany()`, pointing to the `commentable` relationship. This structure uses two special columns in the `comments` table (`commentable_id` and `commentable_type`) to store the ID of the parent model and its class name, respectively, making the association highly flexible without adding redundant columns.