
Pendahuluan
Bayangin lagi ngerjain fitur sederhana, tapi tiba-tiba kebutuhan klien makin melebar hingga bikin struktur database jadi berantakan. Awalnya cuma bikin sistem komentar buat Post, eh besoknya diminta buat Video, lalu nambah lagi buat Product. Kalau kita pakai cara konvensional dengan nambahin kolom foreign key satu-satu di tabel comment, database kita bakal penuh sama kolom null yang nggak perlu. Di sinilah Polymorphic Relationship datang sebagai penyelamat biar tabel kita tetap ramping.
Tips & Best Practices
- Di banyak project, biasanya saya mulai dari menamai kolom morph dengan pola [nama]_id dan [nama]_type secara konsisten agar debugging nggak bikin pusing di kemudian hari.
- Seringkali saat ngerjain aplikasi skala besar, saya memilih untuk memisahkan logika relasi di dalam Trait agar model utama tetap bersih dan nggak penuh sama code boilerplate.
- Dalam hal performa, saya selalu biasain buat nambahin indexing pada kolom morph, karena database bakal sering banget melakukan lookup berdasarkan ID dan type tersebut.
Contoh Kode
Misalnya kita punya fitur komentar yang fleksibel, kita cukup siapin tabel comments dengan struktur morphing seperti ini:
// Migration table comments
Schema::create('comments', function (Blueprint $table) {
$table->id();
$table->text('body');
$table->morphs('commentable'); // Ini bakal bikin commentable_id & commentable_type
$table->timestamps();
});
// Model Comment
public function commentable() {
return $this->morphTo();
}
// Model Post
public function comments() {
return $this->morphMany(Comment::class, 'commentable');
}Variasi Implementasi
Kadang kita ketemu kasus 'Polymorphic Many-to-Many' contohnya sistem tag. Kalau tag ini mau dipakai bareng Post dan Video, kita bisa pakai `morphToMany`. Kelebihannya, kita nggak perlu bikin tabel pivot terpisah, cukup satu tabel `taggables` yang mengikat semuanya. Ini jauh lebih clean dibanding bikin `post_tag` dan `video_tag` secara terpisah.
Kesalahan Umum
- Lupa nge-setup alias di morph map, yang bikin isi kolom *_type jadi string nama class lengkap, kalau kita rename namespace, relasinya langsung putus semua.
- Terlalu antusias pakai morph sampai data yang sebenernya punya perbedaan struktur signifikan dipaksain masuk ke satu tabel, padahal seharusnya dipisah.
- Nggak pakai eager loading (with) saat manggil relasi, akhirnya kena n+1 query yang bikin aplikasi lemot pas di-deploy ke production.
- Gagal melakukan validasi pada input *_type, yang bisa jadi celah kalau kita nggak hati-hati dalam menerima request dari user.
- Mengabaikan indexing pada kolom *_type dan *_id, sehingga query jadi lambat saat tabel comment sudah mencapai jutaan baris.
Ringkasan
Polymorphic relationship itu bukan cuma soal ngurangin jumlah tabel, tapi soal membuat arsitektur aplikasi kita lebih 'tahan banting' terhadap perubahan fitur di masa depan. Kuncinya ada di konsistensi penamaan dan disiplin dalam pemakaian eager loading. Setelah paham konsep ini, saya merasa jauh lebih santai kalau dapet task nambah fitur 'bisa dikomentari' atau 'bisa dilike' ke entitas apapun yang ada di project.
Komentar
Posting Komentar