Di dunia nyata, data saling berhubungan: seorang penulis memiliki banyak artikel, sebuah artikel memiliki banyak komentar, dan sebuah artikel bisa memiliki banyak tag. Menangani hubungan seperti ini dengan query manual akan melelahkan. Di sinilah relasi Eloquent Laravel bersinar — ia membuat data terhubung terasa sealami memanggil properti objek. Artikel ini membahas ketiga relasi utama secara lengkap: One to One, One to Many, dan Many to Many.

Mengapa Relasi Penting?
Tanpa relasi, untuk menampilkan artikel beserta nama penulisnya, Anda harus menulis JOIN manual di setiap query. Dengan Eloquent, cukup tulis $artikel->user->name. Laravel yang mengurus query di belakang layar. Ini membuat kode lebih bersih, mudah dibaca, dan minim kesalahan.
Sebelum mulai, pastikan Anda sudah memahami dasar Migration dan Model. Kita akan memakai contoh: User (pengguna), Post (artikel), Comment (komentar), dan Tag (label).
1. Relasi One to Many (Satu ke Banyak)
Ini relasi paling umum. Contoh: satu User memiliki banyak Post. Sebaliknya, satu Post dimiliki oleh satu User.
Langkah A: Migration dengan Foreign Key
Tabel posts harus punya kolom user_id yang menghubungkannya ke tabel users:
<?php
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->string('judul');
$table->text('isi');
$table->timestamps();
});
}
?>
foreignId('user_id')->constrained() otomatis membuat foreign key ke tabel users. Opsi onDelete('cascade') berarti jika seorang user dihapus, semua post-nya ikut terhapus.
Langkah B: Mendefinisikan Relasi di Model
Di app/Models/User.php, satu user punya banyak post:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
// satu user memiliki banyak post
public function posts()
{
return $this->hasMany(Post::class);
}
}
?>
Lalu di app/Models/Post.php, satu post dimiliki satu user (kebalikannya):
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $fillable = ['user_id', 'judul', 'isi'];
// satu post dimiliki oleh satu user
public function user()
{
return $this->belongsTo(User::class);
}
}
?>
Langkah C: Menggunakan Relasi
Sekarang mengakses data terhubung jadi sangat mudah:
<?php
// ambil semua post milik user #1
$user = User::find(1);
foreach ($user->posts as $post) {
echo $post->judul;
}
// ambil nama penulis dari sebuah post
$post = Post::find(5);
echo $post->user->name; // "Budi"
// membuat post baru lewat relasi (user_id otomatis terisi)
$user->posts()->create([
'judul' => 'Artikel Baru',
'isi' => 'Isi artikel...',
]);
?>
Perhatikan bedanya: $user->posts (tanpa kurung) mengembalikan koleksi data, sedangkan $user->posts() (dengan kurung) mengembalikan query builder yang bisa dilanjutkan, misalnya $user->posts()->latest()->get().
2. Relasi One to One (Satu ke Satu)
Contoh: satu User memiliki satu Profil. Ini dipakai untuk memecah data yang jarang dipakai ke tabel terpisah.
<?php
// di Model User
public function profil()
{
return $this->hasOne(Profil::class);
}
// di Model Profil
public function user()
{
return $this->belongsTo(User::class);
}
?>
Penggunaannya:
<?php $user = User::find(1); echo $user->profil->alamat; // akses data profil ?>
Perbedaan dengan One to Many hanya pada method hasOne (mengembalikan satu objek) versus hasMany (mengembalikan banyak).
3. Relasi Many to Many (Banyak ke Banyak)
Contoh: satu Post punya banyak Tag, dan satu Tag dipakai banyak Post. Relasi ini butuh tabel penghubung (pivot).
Langkah A: Tabel Pivot
Buat tabel post_tag (nama dari gabungan dua tabel, urut abjad):
<?php
Schema::create('post_tag', function (Blueprint $table) {
$table->foreignId('post_id')->constrained()->onDelete('cascade');
$table->foreignId('tag_id')->constrained()->onDelete('cascade');
});
?>
Langkah B: Definisi di Model
<?php
// di Model Post
public function tags()
{
return $this->belongsToMany(Tag::class);
}
// di Model Tag
public function posts()
{
return $this->belongsToMany(Post::class);
}
?>
Langkah C: Menggunakan & Mengelola Pivot
<?php
$post = Post::find(1);
// tampilkan semua tag milik post
foreach ($post->tags as $tag) {
echo $tag->nama;
}
// memasang tag (attach) tanpa menghapus yang lama
$post->tags()->attach([2, 5]);
// melepas tag tertentu
$post->tags()->detach(2);
// mengganti semua tag sekaligus (sync)
$post->tags()->sync([1, 3, 4]);
?>
Method sync() sangat berguna pada form edit: cukup kirim array id tag terpilih, Laravel otomatis menambah yang baru dan menghapus yang tidak dipilih.
Menghindari Masalah N+1 dengan Eager Loading
Ini konsep penting yang sering dilupakan pemula. Perhatikan kode ini:
<?php
$posts = Post::all();
foreach ($posts as $post) {
echo $post->user->name; // query dijalankan BERULANG tiap loop!
}
?>
Jika ada 100 post, kode di atas menjalankan 1 query untuk post + 100 query untuk user = 101 query (masalah “N+1”). Situs jadi lambat. Solusinya adalah eager loading dengan with():
<?php
$posts = Post::with('user')->get(); // hanya 2 query total
foreach ($posts as $post) {
echo $post->user->name;
}
?>
Untuk relasi bertingkat, gunakan titik: Post::with('comments.user')->get() memuat komentar beserta user tiap komentar.
Menampilkan di Blade
@foreach ($posts as $post)
<h3>{{ $post->judul }}</h3>
<small>oleh {{ $post->user->name }}</small>
<p>{{ $post->comments->count() }} komentar</p>
@foreach ($post->tags as $tag)
<span class="tag">{{ $tag->nama }}</span>
@endforeach
@endforeach
Ringkasan Tiga Relasi
| Relasi | Method (induk) | Method (anak) | Butuh Pivot? |
|---|---|---|---|
| One to One | hasOne | belongsTo | Tidak |
| One to Many | hasMany | belongsTo | Tidak |
| Many to Many | belongsToMany | belongsToMany | Ya |
Kesalahan Umum
- Salah penamaan foreign key — Laravel mengharapkan
user_iduntuk relasi ke tabelusers. Jika berbeda, tentukan manual:hasMany(Post::class, 'penulis_id'). - Lupa eager loading — menyebabkan masalah N+1 dan situs lambat. Gunakan
with()saat menampilkan banyak data berelasi. - Nama tabel pivot salah — harus gabungan singular dua tabel urut abjad (
post_tag, bukantag_postatauposts_tags). - Bingung
$user->postsvs$user->posts()— tanpa kurung = data, dengan kurung = query yang bisa dilanjutkan.
Kesimpulan
Anda telah menguasai tiga relasi Eloquent Laravel: One to One (hasOne), One to Many (hasMany), dan Many to Many (belongsToMany) — lengkap dari migration, model, penggunaan, hingga eager loading untuk performa. Relasi adalah salah satu fitur Laravel yang paling menghemat waktu. Kuasai ini, dan Anda bisa membangun aplikasi kompleks (blog, e-commerce, forum) dengan kode yang jauh lebih ringkas. Langkah berikutnya, pelajari validasi form agar data yang masuk ke relasi ini selalu bersih dan valid.
Referensi: untuk pendalaman, kunjungi dokumentasi resmi Laravel.

