Home Arrow Icon Knowledge base Arrow Icon Global Arrow Icon Can you show an example of using morphToMany with a pivot table


Can you show an example of using morphToMany with a pivot table


Here is a detailed example of using Laravel's `morphToMany` relationship with a pivot table, including how to define the relationship, the pivot table schema, and how to access pivot data.

Scenario

Suppose you have multiple models, such as `Post` and `Video`, that can be tagged with multiple `Tag` models. This is a classic polymorphic many-to-many relationship where tags can belong to different models.

Step 1: Define Models and Relationships

Post Model

php
use Illuminate\Database\Eloquent\Model;

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

Video Model

php
use Illuminate\Database\Eloquent\Model;

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

Tag Model

php
use Illuminate\Database\Eloquent\Model;

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

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

Here, `morphToMany` is defined on the models that can be tagged (`Post` and `Video`), and `morphedByMany` is defined on the `Tag` model to access the inverse relationship[5].

Step 2: Create the Pivot Table Migration

The pivot table for a polymorphic many-to-many relationship typically follows this structure:

php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateTaggablesTable extends Migration
{
    public function up()
    {
        Schema::create('taggables', function (Blueprint $table) {
            $table->id();
            $table->foreignId('tag_id')->constrained()->onDelete('cascade');
            $table->morphs('taggable'); // creates taggable_id and taggable_type columns
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('taggables');
    }
}

The `morphs('taggable')` method creates two columns: `taggable_id` (unsigned bigint) and `taggable_type` (string), which Laravel uses to identify the related model and its ID[4][5].

Step 3: Using Pivot Data

If you want to add extra fields to the pivot table (for example, a `priority` or `assigned_by`), you can add those columns to the pivot table migration:

php
$table->string('assigned_by')->nullable();
$table->integer('priority')->default(0);

Then, in your model relationship, you can access these pivot fields by specifying `withPivot()`:

php
public function tags()
{
    return $this->morphToMany(Tag::class, 'taggable')
                ->withPivot('assigned_by', 'priority')
                ->withTimestamps();
}

You can then access pivot data like this:

php
$post = Post::find(1);
foreach ($post->tags as $tag) {
    echo $tag->pivot->assigned_by;
    echo $tag->pivot->priority;
}

Step 4: Using a Custom Pivot Model (Optional)

If you want to add methods or casts to the pivot model, create a custom pivot model that extends `Illuminate\Database\Eloquent\Relations\MorphPivot`:

php
namespace App\Models\Pivots;

use Illuminate\Database\Eloquent\Relations\MorphPivot;

class Taggable extends MorphPivot
{
    // Custom methods or casts here
}

Then specify it in your relationship:

php
public function tags()
{
    return $this->morphToMany(Tag::class, 'taggable')
                ->using(\App\Models\Pivots\Taggable::class)
                ->withPivot('assigned_by', 'priority')
                ->withTimestamps();
}

Summary

- Use `morphToMany` on models that own the polymorphic relation.
- Use `morphedByMany` on the related model.
- Create a pivot table with `tag_id`, `taggable_id`, and `taggable_type`.
- Add extra pivot fields in the migration and use `withPivot()` to access them.
- Optionally, define a custom pivot model extending `MorphPivot` for advanced pivot handling.

This approach allows you to manage polymorphic many-to-many relationships with pivot data effectively in Laravel[4][5][6][7][8].

Citations:
[1] https://stackoverflow.com/questions/68073778/laravel-polymorphic-many-to-many-relationship-pivot-table-with-relationship-to-a
[2] https://laracasts.com/discuss/channels/laravel/polymorphic-relationship-and-accessing-method-on-pivot-table
[3] https://www.youtube.com/watch?v=24EpLfImj84
[4] https://laravel.com/docs/11.x/eloquent-relationships
[5] https://larawiz.github.io/docs/model-relations/many-to-many-and-polymorphic
[6] https://stackoverflow.com/questions/59437157/polymorphic-relationship-with-pivot-data
[7] https://github.com/laravel/framework/discussions/39638
[8] https://laravel.com/docs/12.x/eloquent-relationships