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.