Laravel Basic
Laravel Form
Laravel Database
Laravel Advance
A Polymorphic Many To Many relationship allows multiple models to share a common relationship with another model using a single pivot table.
👉 In this example:
playlistables
.Playlist ↔ Songs Playlist ↔ Videos Playlist ↔ Podcasts
Flow diagram
Use this command to generate a migration for creating a tables:
php artisan make:migration create_polymorphic_many_to_many_tables
public function up(): void { // Playlists Schema::create('playlists', function (Blueprint $table) { $table->id(); $table->string('name'); $table->timestamps(); }); // Songs Schema::create('songs', function (Blueprint $table) { $table->id(); $table->string('title'); $table->string('artist')->nullable(); $table->timestamps(); }); // Videos Schema::create('videos', function (Blueprint $table) { $table->id(); $table->string('title'); $table->string('channel')->nullable(); $table->timestamps(); }); // Podcasts Schema::create('podcasts', function (Blueprint $table) { $table->id(); $table->string('title'); $table->string('host')->nullable(); $table->timestamps(); }); // Polymorphic pivot table Schema::create('playlistables', function (Blueprint $table) { $table->id(); $table->unsignedBigInteger('playlist_id'); $table->unsignedBigInteger('playlistable_id'); $table->string('playlistable_type'); $table->timestamps(); $table->foreign('playlist_id')->references('id')->on('playlists')->onDelete('cascade'); }); } public function down(): void { Schema::dropIfExists('playlistables'); Schema::dropIfExists('podcasts'); Schema::dropIfExists('videos'); Schema::dropIfExists('songs'); Schema::dropIfExists('playlists'); }
Run Migration
php artisan migrate
id | title | artist | created_at | updated_at |
---|
id | title | channel | created_at | updated_at |
---|
id | title | host | created_at | updated_at |
---|
id | name | created_at | updated_at |
---|
id | playlist_id | playlistable_id | playlistable_type | created_at | updated_at |
---|
Generate a model with Artisan:
php artisan make:model Playlist php artisan make:model Song php artisan make:model Video php artisan make:model Podcast
This generates 4 files Playlist.php , Song.php ,Video.php and Podcast.php
namespace App\Models; use App\Models\Playlist; use Illuminate\Database\Eloquent\Model; class Song extends Model { protected $fillable = ['title', 'artist']; public function playlists() { return $this->morphToMany(Playlist::class, 'playlistable'); } }
namespace App\Models; use App\Models\Playlist; use Illuminate\Database\Eloquent\Model; class Video extends Model { protected $fillable = ['title', 'channel']; public function playlists() { return $this->morphToMany(Playlist::class, 'playlistable'); } }
namespace App\Models; use App\Models\Playlist; use Illuminate\Database\Eloquent\Model; class Podcast extends Model { protected $fillable = ['title', 'host']; public function playlists() { return $this->morphToMany(Playlist::class, 'playlistable'); } }
namespace App\Models; use App\Models\Song; use App\Models\Video; use App\Models\Podcast; use Illuminate\Database\Eloquent\Model; class Playlist extends Model { protected $fillable = ['name']; public function songs() { return $this->morphedByMany(Song::class, 'playlistable'); } public function videos() { return $this->morphedByMany(Video::class, 'playlistable'); } public function podcasts() { return $this->morphedByMany(Podcast::class, 'playlistable'); } }
use App\Models\Song; use App\Models\Video; use App\Models\Podcast; use App\Models\Playlist; // Create Playlist $playlist = Playlist::create(['name' => 'My Favorites']); // Create a Song and attach to Playlist $song = Song::create(['title' => 'Shape of You', 'artist' => 'Ed Sheeran']); $playlist->songs()->attach($song->id); // Create a Video and attach to Playlist $video = Video::create(['title' => 'Laravel Tutorial', 'channel' => 'Code Academy']); $playlist->videos()->attach($video->id); // Create a Podcast and attach to Playlist $podcast = Podcast::create(['title' => 'Tech Talk', 'host' => 'John Doe']); $playlist->podcasts()->attach($podcast->id);
id | title | artist | created_at | updated_at |
---|---|---|---|---|
1 | Shape of You | Ed Sheeran | 2025-08-28 07:36:16 | 2025-08-28 07:36:16 |
id | title | channel | created_at | updated_at |
---|---|---|---|---|
1 | Laravel Tutorial | Code Academy | 2025-08-28 07:36:16 | 2025-08-28 07:36:16 |
id | title | host | created_at | updated_at |
---|---|---|---|---|
1 | Tech Talk | John Doe | 2025-08-28 07:36:16 | 2025-08-28 07:36:16 |
id | name | created_at | updated_at |
---|---|---|---|
1 | My Favorites | 2025-08-28 07:36:16 | 2025-08-28 07:36:16 |
id | playlist_id | playlistable_id | playlistable_type | created_at | updated_at |
---|---|---|---|---|---|
1 | 1 | 1 | App\Models\Song | 2025-08-28 07:36:16 | 2025-08-28 07:36:16 |
2 | 1 | 1 | App\Models\Video | 2025-08-28 07:36:16 | 2025-08-28 07:36:16 |
3 | 1 | 1 | App\Models\Podcast | 2025-08-28 07:36:16 | 2025-08-28 07:36:16 |
use App\Models\Song; use App\Models\Video; use App\Models\Podcast; use App\Models\Playlist; // Get all Songs in a Playlist $playlist = Playlist::find(1); foreach ($playlist->songs as $song) { echo $song->title . " by " . $song->artist."<br>"; } // Get all Videos in a Playlist $playlist = Playlist::find(1); foreach ($playlist->videos as $video) { echo $video->title . " from " . $video->channel."<br>"; } // Get all Podcasts in a Playlist $playlist = Playlist::find(1); foreach ($playlist->podcasts as $podcast) { echo $podcast->title . " hosted by " . $podcast->host."<br>"; } // Get Playlist from a Song $song = Song::find(1); foreach ($song->playlists as $playlist) { echo $playlist->name."<br>"; }
// Update Playlist name $playlist = Playlist::find(1); $playlist->update(['name' => 'Updated Playlist']); // Update Song in Playlist $song = Song::find(1); $song->update(['title' => 'Perfect']); // Sync Songs (Update Attached Songs List) $playlist = Playlist::find(1); $playlist->songs()->sync([2, 3]); // Replace all songs with only songs 2, 3 // Sync Without Detaching (Keep Old Songs + Add New) $playlist = Playlist::find(1); $playlist->songs()->syncWithoutDetaching([4, 5]); // Add songs 4 & 5 without removing existing songs
// Remove one Song from Playlist $playlist = Playlist::find(1); $playlist->songs()->detach(1); // Detach song with id 1 // Remove all Videos from Playlist $playlist->videos()->detach(); // Delete a Playlist (will not delete songs/videos/podcasts themselves) $playlist->delete();
use App\Models\Song; use App\Models\Video; use App\Models\Podcast; use App\Models\Playlist; // Get all Songs in a Playlist $playlist = Playlist::with('songs')->find(1); foreach ($playlist->songs as $song) { echo $song->title . " by " . $song->artist; } // Get all Videos in a Playlist $playlist = Playlist::with('videos')->find(1); foreach ($playlist->videos as $video) { echo $video->title . " from " . $video->channel; } // Get all Podcasts in a Playlist $playlist = Playlist::with('podcasts')->find(1); foreach ($playlist->podcasts as $podcast) { echo $podcast->title . " hosted by " . $podcast->host; } // Get Playlist from a Song $song = Song::with('playlists')->find(1); foreach ($song->playlists as $playlist) { echo $playlist->name; }
Always use with()
when fetching related data in bulk.