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