Laravel one-to-many polymorphic relationship

Laravel one-to-many polymorphic relationship

In this article let’s understand Laravel one-to-many polymorphic relationship.

Laravel provides many relationship to work with multiple tables and one of them is one-to-many polymorphic relationship.

Check below graphics to understand it in simple scenario.

What you can see from graphics is one Post can have many Tags as well one Video can also have many Tags. When “Post” & “Video” both can share “Tags” table we can use one-to-many polymorphic relationship.

Let’s understand it through example where we have:

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

This will create three models and three migrations as below:

app/Models/
    Post.php
    Video.php
    Tag.php

database/migrations/
    ***_create_posts_table.php
    ***_create_videos_table.php
    ***_create_tags_table.php

Update all three migrations as below for each:

//Country
Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->timestamps();
});

//State
Schema::create('videos', function (Blueprint $table) {
    $table->id();
    $table->text('title');
    $table->timestamps();
});

// Capital
 Schema::create('tags', function (Blueprint $table) {
    $table->id();
    $table->morphs('taggable');
    $table->text('name');
    $table->timestamps();
});

The morphs(‘taggable’) will create two columns as “taggable_id” & “taggable_type”.

The taggable_type will save model reference for mapping, taggable_id will be the reference model id.

The relationship between three tables will be defined as

  • morphToMany : post->tag
  • morphToMany : video->tag
  • morphTo : tag

Open app/Models/Post.php and modify as below:

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

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

Check app/Models/Video.php and modify as blow:

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

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

Check app/Models/Tag.php and modify as blow:


namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Tag extends Model
{
    use HasFactory;
    public function taggable()
    {
        return $this->morphTo();
    }
}

Run Migrations:

php artisan migrate

Use below methods in your controller to check how one-to-many polymorphic relationship works:

// Create a new tag
$tag = Tag::create(['name' => 'Laravel']);

// Create a new post and associate the tag
$post = Post::create(['title' => 'New Post']);
$post->tags()->attach($tag);

// Create a new video and associate the tag
$video = Video::create(['title' => 'New Video']);
$video->tags()->attach($tag);

// Retrieve all tags for a post or video
$tagsForPost = $post->tags;
$tagsForVideo = $video->tags;

// Retrieve all posts and videos associated with a specific tag
$laravelTag = Tag::where('name', 'Laravel')->first();
$postsWithTag = $laravelTag->posts;
$videosWithTag = $laravelTag->videos;

This is very basic and simple implementation of this relationship, but just to make you understand it’s concept. You can play with its various implementation as per your need.

That’s it on one-to-many polymorphic . Hope this finds you helpful.

See other articles on Laravel here.