TechTopia Casing SSD NVMe NGFF USB 3.1 Type-C Enclosure Eksternal M.2 SATA & NVMe High Speed

Laravel Eloquent Relationship: Belajar One to One, One to Many, dan Many to Many

Dalam aplikasi Laravel, data hampir selalu memiliki hubungan dengan data lainnya. User dapat memiliki profile. Satu user dapat membuat banyak artikel. Satu artikel dapat memiliki banyak komentar. Di sisi lain, satu artikel juga dapat memiliki banyak tag, dan satu tag dapat digunakan oleh banyak artikel.

Jika hubungan tersebut ditangani menggunakan query database secara manual di berbagai tempat, kode aplikasi akan cepat menjadi rumit.

Laravel menyediakan Eloquent Relationship untuk mengatasi masalah tersebut.

Dengan Eloquent Relationship, hubungan antar-tabel dapat didefinisikan langsung pada model sehingga kode menjadi lebih ekspresif, mudah dibaca, dan lebih mudah dipelihara.

Artikel ini membahas konsep relationship Eloquent dari dasar hingga praktik yang umum digunakan dalam aplikasi Laravel.

Apa Itu Eloquent Relationship?

Eloquent Relationship adalah fitur Laravel Eloquent ORM yang memungkinkan sebuah model berhubungan dengan model lainnya berdasarkan relasi antar-tabel di database.

Misalnya terdapat dua tabel:

users
    ↓
posts

Seorang user dapat memiliki banyak post.

Dalam model User, hubungan tersebut dapat ditulis:

public function posts(): HasMany
{
    return $this->hasMany(Post::class);
}

Setelah relationship dibuat, data dapat diakses dengan:

$user->posts;

Eloquent akan menangani query database yang diperlukan untuk mengambil post milik user tersebut.

Mengapa Relationship Penting?

Tanpa relationship, developer mungkin harus menulis query secara manual setiap kali membutuhkan data yang berhubungan.

Dengan relationship, kode dapat dibuat lebih deklaratif.

Contohnya:

$user->posts;

lebih mudah dipahami daripada harus mengulang query berdasarkan user_id di banyak tempat.

Relationship juga membantu ketika aplikasi memiliki struktur data yang kompleks.

Misalnya:

User
 ├── Profile
 └── Posts
      ├── Comments
      └── Tags

Model dapat merepresentasikan hubungan tersebut secara langsung.

Konsep Foreign Key

Sebelum memahami relationship Eloquent, penting untuk memahami foreign key.

Misalnya tabel users memiliki:

id
name
email

Kemudian tabel posts memiliki:

id
user_id
title
content

posts.user_id adalah foreign key yang menunjuk ke users.id.

Secara konsep:

users.id
   ↑
   |
posts.user_id

Eloquent menggunakan struktur tersebut untuk mengetahui bagaimana dua model berhubungan.

Tiga Relationship Dasar yang Wajib Dipahami

Dalam aplikasi Laravel, tiga relationship yang paling sering digunakan adalah:

  1. One to One
  2. One to Many
  3. Many to Many

Selain itu Laravel juga memiliki relationship yang lebih lanjut, seperti:

  • Has One Through
  • Has Many Through
  • One of Many
  • Polymorphic One to One
  • Polymorphic One to Many
  • Polymorphic Many to Many

Untuk memahami relationship secara kuat, tiga tipe dasar sebaiknya dikuasai terlebih dahulu.

One to One

One to One berarti satu record memiliki satu record yang berhubungan.

Contoh paling mudah adalah:

User
 ↓
Profile

Satu user memiliki satu profile.

Struktur database dapat dibuat seperti:

users
├── id
├── name
└── email

profiles
├── id
├── user_id
└── bio

Karena foreign key berada pada tabel profiles, maka Profile memiliki hubungan dengan User.

Migration untuk One to One

Migration users:

Schema::create('users', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->string('email')->unique();
    $table->timestamps();
});

Migration profiles:

Schema::create('profiles', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')
        ->unique()
        ->constrained()
        ->cascadeOnDelete();

    $table->text('bio')->nullable();
    $table->timestamps();
});

Perhatikan penggunaan:

->unique()

Jika setiap user hanya boleh memiliki satu profile, user_id sebaiknya dibuat unique.

Dengan demikian database juga membantu memastikan aturan One to One tersebut.

hasOne() pada Model User

Pada model User:

use Illuminate\Database\Eloquent\Relations\HasOne;

public function profile(): HasOne
{
    return $this->hasOne(Profile::class);
}

Sekarang profile dapat diambil dengan:

$user = User::find(1);

$profile = $user->profile;

belongsTo() pada Model Profile

Relationship dari arah sebaliknya:

use Illuminate\Database\Eloquent\Relations\BelongsTo;

public function user(): BelongsTo
{
    return $this->belongsTo(User::class);
}

Sekarang:

$profile = Profile::find(1);

$user = $profile->user;

Keduanya dapat digunakan karena relationship didefinisikan pada kedua model.

Cara Memahami hasOne() dan belongsTo()

Kesalahan umum developer pemula adalah menghafalkan method tanpa memahami arahnya.

Gunakan aturan sederhana:

User
 ↓ hasOne()
Profile

Artinya:

User memiliki satu Profile.

Sedangkan:

Profile
 ↓ belongsTo()
User

Artinya:

Profile dimiliki oleh User.

Perhatikan model yang sedang menjadi titik awal relationship.

One to Many

One to Many berarti satu record memiliki banyak record lainnya.

Contoh:

User
 ↓
Posts

Satu user dapat memiliki banyak post.

Tetapi satu post hanya memiliki satu user.

Strukturnya:

users
├── id
├── name
└── email

posts
├── id
├── user_id
├── title
└── content

Migration One to Many

Migration posts:

Schema::create('posts', function (Blueprint $table) {
    $table->id();

    $table->foreignId('user_id')
        ->constrained()
        ->cascadeOnDelete();

    $table->string('title');
    $table->text('content');
    $table->timestamps();
});

Berbeda dengan One to One, user_id tidak dibuat unique.

Alasannya karena satu user boleh memiliki banyak post.

Contohnya:

users
id = 1

posts
id = 1, user_id = 1
id = 2, user_id = 1
id = 3, user_id = 1

hasMany() pada Model User

Pada User:

use Illuminate\Database\Eloquent\Relations\HasMany;

public function posts(): HasMany
{
    return $this->hasMany(Post::class);
}

Mengambil semua post:

$user = User::find(1);

$posts = $user->posts;

Karena hasilnya berupa collection, data dapat diproses menggunakan loop:

foreach ($user->posts as $post) {
    echo $post->title;
}

belongsTo() pada Model Post

Pada Post:

use Illuminate\Database\Eloquent\Relations\BelongsTo;

public function user(): BelongsTo
{
    return $this->belongsTo(User::class);
}

Sekarang:

$post = Post::find(1);

echo $post->user->name;

Relasinya menjadi:

User
 ↓ hasMany()
Posts

Post
 ↓ belongsTo()
User

Membuat Data Melalui Relationship

Relationship juga dapat digunakan untuk membuat record baru.

Misalnya:

$user->posts()->create([
    'title' => 'Belajar Laravel',
    'content' => 'Memahami Eloquent Relationship',
]);

Laravel akan mengisi user_id berdasarkan user yang menjadi parent relationship.

Ini lebih nyaman dibanding:

Post::create([
    'user_id' => $user->id,
    'title' => 'Belajar Laravel',
    'content' => 'Memahami Eloquent Relationship',
]);

Keduanya valid, tetapi relationship membuat konteks parent-child lebih eksplisit.

Mass Assignment pada Relationship

Saat menggunakan:

$user->posts()->create([
    'title' => 'Belajar Laravel',
    'content' => '...',
]);

model Post tetap perlu mengizinkan field yang digunakan.

Contoh:

protected $fillable = [
    'title',
    'content',
];

Jangan memasukkan field sensitif atau field yang tidak seharusnya dapat diisi melalui mass assignment.

Menambahkan Beberapa Record Melalui Relationship

Untuk membuat banyak record sekaligus, Anda juga dapat menggunakan:

$user->posts()->createMany([
    [
        'title' => 'Artikel Pertama',
        'content' => 'Isi artikel pertama',
    ],
    [
        'title' => 'Artikel Kedua',
        'content' => 'Isi artikel kedua',
    ],
]);

Foreign key tetap diatur berdasarkan relationship.

Many to Many

Many to Many terjadi ketika banyak record dapat berhubungan dengan banyak record lainnya.

Contoh populer:

Posts
  ↕
Tags

Satu post dapat memiliki banyak tag.

Satu tag juga dapat digunakan oleh banyak post.

Contohnya:

Post A
├── Laravel
├── PHP
└── Backend

Post B
├── Laravel
└── Database

Karena satu post memiliki banyak tag dan satu tag dapat digunakan banyak post, dibutuhkan tabel penghubung.

Apa Itu Pivot Table?

Pivot table adalah tabel yang menghubungkan dua tabel dalam relationship Many to Many.

Misalnya:

posts
tags
post_tag

Tabel post_tag:

post_id
tag_id

Strukturnya:

posts
   ↓
post_tag
   ↑
tags

Migration Pivot Table

Migration dapat dibuat seperti:

Schema::create('post_tag', function (Blueprint $table) {
    $table->foreignId('post_id')
        ->constrained()
        ->cascadeOnDelete();

    $table->foreignId('tag_id')
        ->constrained()
        ->cascadeOnDelete();

    $table->primary(['post_id', 'tag_id']);
});

Primary key gabungan tersebut mencegah kombinasi post dan tag yang sama dimasukkan lebih dari sekali.

belongsToMany()

Pada model Post:

use Illuminate\Database\Eloquent\Relations\BelongsToMany;

public function tags(): BelongsToMany
{
    return $this->belongsToMany(Tag::class);
}

Pada model Tag:

use Illuminate\Database\Eloquent\Relations\BelongsToMany;

public function posts(): BelongsToMany
{
    return $this->belongsToMany(Post::class);
}

Sekarang:

$post->tags;

akan mengambil semua tag yang berhubungan dengan post.

Sedangkan:

$tag->posts;

mengambil semua post yang menggunakan tag tersebut.

Menambahkan Relationship dengan attach()

Misalnya post dengan ID 1 ingin diberi tag dengan ID 2:

$post->tags()->attach(2);

Beberapa tag sekaligus:

$post->tags()->attach([1, 2, 3]);

Anda juga dapat memasukkan data pivot tambahan:

$post->tags()->attach([
    1 => ['created_by' => 10],
]);

Tentu saja kolom created_by harus tersedia pada pivot table.

Menghapus Relationship dengan detach()

Untuk menghapus hubungan tertentu:

$post->tags()->detach(2);

Menghapus beberapa relationship:

$post->tags()->detach([1, 2]);

Menghapus semua relationship:

$post->tags()->detach();

Perintah tersebut menghapus relationship dari pivot table, bukan menghapus record Tag dari tabel tags.

Menggunakan sync()

sync() sangat berguna ketika aplikasi memiliki form yang mengirim daftar ID terbaru.

Misalnya:

$post->tags()->sync([1, 3, 5]);

Laravel akan menyesuaikan isi pivot table sehingga relationship yang tersisa adalah tag 13, dan 5.

Tag yang sebelumnya terhubung tetapi tidak ada dalam array dapat dilepas.

syncWithoutDetaching()

Jika ingin menambahkan relationship tanpa menghapus relationship yang sudah ada:

$post->tags()->syncWithoutDetaching([4, 5]);

Ini berguna ketika aplikasi ingin menambahkan beberapa tag tanpa memengaruhi tag yang sudah terpasang.

Pivot Table dengan Kolom Tambahan

Pivot table tidak selalu hanya berisi dua foreign key.

Contohnya relationship:

User
 ↕
Course

Tabel pivot:

course_user
├── user_id
├── course_id
├── enrolled_at
└── status

Kolom tambahan tersebut dapat menyimpan informasi tentang relationship.

Mengakses Data Pivot

Pada model:

public function courses(): BelongsToMany
{
    return $this->belongsToMany(Course::class)
        ->withPivot('enrolled_at', 'status');
}

Kemudian:

foreach ($user->courses as $course) {
    echo $course->pivot->status;
}

Property pivot berisi data dari tabel pivot.

Memberi Nama Pivot Model

Jika pivot memiliki logic yang cukup kompleks, Anda dapat menggunakan custom pivot model.

Contohnya:

return $this->belongsToMany(Course::class)
    ->using(CourseUser::class);

Pendekatan ini berguna ketika pivot bukan sekadar tabel penghubung sederhana, tetapi memiliki perilaku atau aturan bisnis tertentu.

Custom Foreign Key

Laravel menggunakan konvensi penamaan untuk menebak foreign key.

Contoh:

return $this->hasMany(Post::class);

Laravel biasanya mencari:

posts.user_id

Namun, jika kolom Anda bernama:

posts.author_id

relationship dapat ditulis:

return $this->hasMany(Post::class, 'author_id');

Ini berguna ketika database menggunakan naming convention yang berbeda.

Custom Local Key

Jika primary key parent bukan id, key tersebut juga dapat ditentukan.

Contoh:

return $this->hasMany(Post::class, 'author_id', 'uuid');

Artinya relationship menggunakan:

posts.author_id

yang mengarah ke:

users.uuid

Pastikan struktur database memang menggunakan key tersebut.

Custom Pivot Table

Laravel biasanya dapat menebak nama pivot table berdasarkan nama model.

Untuk Post dan Tag, Laravel mengharapkan:

post_tag

Jika nama pivot berbeda, tentukan secara eksplisit:

return $this->belongsToMany(
    Tag::class,
    'article_categories'
);

Foreign key pivot juga dapat ditentukan jika struktur database tidak mengikuti konvensi Laravel.

Eager Loading

Salah satu konsep terpenting dalam relationship adalah eager loading.

Misalnya Anda mengambil semua post:

$posts = Post::all();

Kemudian:

foreach ($posts as $post) {
    echo $post->user->name;
}

Kode tersebut terlihat sederhana, tetapi dapat menghasilkan banyak query database.

Masalah ini dikenal sebagai N+1 query problem.

Solusinya:

$posts = Post::with('user')->get();

Kemudian:

foreach ($posts as $post) {
    echo $post->user->name;
}

Relationship user sudah dimuat bersama data post.

Apa Itu N+1 Query Problem?

Misalnya terdapat 100 post.

Aplikasi menjalankan:

1 query
→ mengambil 100 posts

100 query
→ mengambil user masing-masing post

Total dapat menjadi sekitar:

101 queries

Inilah yang disebut N+1.

Dengan eager loading:

Post::with('user')->get();

Eloquent dapat mengambil data relationship secara lebih efisien.

Secara konsep:

1 query
→ posts

1 query
→ users terkait

Jumlah query dapat jauh lebih sedikit.

Eager Loading Banyak Relationship

Jika sebuah halaman membutuhkan user dan tags:

$posts = Post::with([
    'user',
    'tags',
])->get();

Relationship dapat dimuat sekaligus.

Nested Eager Loading

Relationship juga dapat dimuat secara bertingkat.

Misalnya:

Post
 ↓
User
 ↓
Profile

Gunakan:

$posts = Post::with('user.profile')->get();

Untuk relationship yang lebih kompleks:

$posts = Post::with([
    'user.profile',
    'tags',
])->get();

Gunakan eager loading hanya untuk relationship yang benar-benar dibutuhkan.

Eager Loading dengan Kondisi

Anda dapat memberikan constraint:

$posts = Post::with([
    'comments' => function ($query) {
        $query->latest();
    },
])->get();

Ini berguna ketika relationship membutuhkan filtering atau ordering tertentu.

Lazy Eager Loading dengan load()

Terkadang model sudah terlanjur diambil:

$posts = Post::all();

Kemudian Anda baru mengetahui bahwa membutuhkan user.

Anda dapat menggunakan:

$posts->load('user');

Ini berbeda dari:

Post::with('user')->get();

karena with() digunakan sebelum query utama dijalankan, sedangkan load() digunakan setelah model sudah tersedia.

loadMissing()

Jika ingin memuat relationship hanya jika belum dimuat:

$posts->loadMissing('user');

Ini berguna dalam kode yang dipanggil dari beberapa bagian aplikasi dan ingin menghindari pemuatan relationship yang sama secara tidak perlu.

Memeriksa Relationship yang Sudah Dimuat

Eloquent menyediakan:

$post->relationLoaded('user');

Contohnya:

if ($post->relationLoaded('user')) {
    // relationship sudah tersedia
}

Hal ini dapat membantu ketika Anda ingin memastikan akses relationship tidak memicu query tambahan secara tidak sengaja.

has() untuk Mencari Model yang Memiliki Relationship

Misalnya ingin mengambil user yang memiliki setidaknya satu post:

$users = User::has('posts')->get();

Laravel akan mencari user berdasarkan keberadaan relationship tersebut.

Anda juga dapat menentukan jumlah:

$users = User::has('posts', '>=', 5)->get();

Artinya mengambil user yang memiliki minimal lima post.

whereHas() untuk Filtering Relationship

Misalnya ingin mencari user yang memiliki post dengan status published:

$users = User::whereHas('posts', function ($query) {
    $query->where('status', 'published');
})->get();

Ini sangat berguna untuk filter berdasarkan data relationship.

Contoh lainnya:

$posts = Post::whereHas('tags', function ($query) {
    $query->where('name', 'Laravel');
})->get();

Artinya mengambil post yang memiliki tag Laravel.

whereDoesntHave()

Untuk mencari model yang tidak memiliki relationship tertentu:

$users = User::whereDoesntHave('posts')->get();

Artinya mengambil user yang belum memiliki post.

Menghitung Relationship dengan withCount()

Jika hanya membutuhkan jumlah relationship, tidak selalu perlu mengambil seluruh datanya.

Contoh:

$users = User::withCount('posts')->get();

Sekarang setiap user memiliki property:

$user->posts_count;

Contoh penggunaan:

foreach ($users as $user) {
    echo $user->name;
    echo $user->posts_count;
}

Ini lebih tepat ketika halaman hanya membutuhkan jumlah data, bukan seluruh post.

withExists()

Jika aplikasi hanya ingin mengetahui apakah relationship tersedia, Anda dapat menggunakan:

$users = User::withExists('posts')->get();

Kemudian dapat memeriksa property yang dihasilkan untuk mengetahui apakah user memiliki post.

Ini dapat menjadi alternatif yang lebih tepat daripada mengambil seluruh relationship hanya untuk mengecek keberadaannya.

Relationship dengan Soft Delete

Jika model yang berhubungan menggunakan Soft Deletes, hasil relationship dapat dipengaruhi oleh global scope soft delete.

Misalnya:

$post->user;

Jika user terkait sudah di-soft-delete, user tersebut mungkin tidak muncul pada relationship normal.

Untuk kebutuhan tertentu, relationship dapat dikonfigurasi agar menyertakan data yang sudah di-soft-delete.

Contohnya:

public function user(): BelongsTo
{
    return $this->belongsTo(User::class)->withTrashed();
}

Gunakan pendekatan tersebut hanya jika memang sesuai dengan aturan bisnis aplikasi.

withDefault() untuk Relationship yang Tidak Ada

Bayangkan sebuah Post dapat memiliki user yang belum tersedia.

Daripada:

$post->user->name;

menghasilkan error ketika user tidak ada, relationship dapat menggunakan default model:

public function user(): BelongsTo
{
    return $this->belongsTo(User::class)
        ->withDefault();
}

Default object tersebut dapat mencegah error ketika relationship kosong.

Anda juga dapat memberikan nilai default:

public function user(): BelongsTo
{
    return $this->belongsTo(User::class)
        ->withDefault([
            'name' => 'Guest',
        ]);
}

Nullable Relationship

Tidak semua relationship wajib tersedia.

Misalnya sebuah post boleh dibuat tanpa author tertentu.

Migration dapat menggunakan:

$table->foreignId('user_id')
    ->nullable()
    ->constrained()
    ->nullOnDelete();

Dengan begitu, ketika user dihapus, user_id dapat menjadi NULL.

Model:

public function user(): BelongsTo
{
    return $this->belongsTo(User::class);
}

Ketika mengakses:

$post->user;

hasilnya dapat berupa null.

Karena itu kode aplikasi perlu menangani kemungkinan tersebut.

Kesalahan Umum: Salah Menentukan Relationship

Contoh yang sering terjadi:

public function user()
{
    return $this->hasOne(User::class);
}

pada model Post.

Jika tabel posts memiliki user_id, biasanya yang benar:

public function user(): BelongsTo
{
    return $this->belongsTo(User::class);
}

Ingat:

User memiliki Post
→ hasMany()

Post dimiliki User
→ belongsTo()

Kesalahan Umum: Foreign Key Tidak Sesuai

Relationship dapat terlihat benar tetapi gagal karena nama kolom tidak sesuai.

Misalnya model mengharapkan:

user_id

tetapi database memiliki:

author_id

Jika menggunakan naming custom, tentukan foreign key secara eksplisit:

return $this->belongsTo(User::class, 'author_id');

Kesalahan Umum: Pivot Table Tidak Sesuai Konvensi

Laravel memiliki konvensi penamaan pivot table.

Jika Laravel mengharapkan:

post_tag

tetapi database memiliki:

post_tags

relationship dapat gagal jika nama tersebut tidak dikonfigurasi dengan benar.

Jika menggunakan nama custom:

return $this->belongsToMany(
    Tag::class,
    'post_tags'
);

Kesalahan Umum: Tidak Menggunakan Eager Loading

Kode seperti:

$posts = Post::all();

foreach ($posts as $post) {
    echo $post->user->name;
}

dapat menjadi masalah ketika jumlah data besar.

Biasakan mengevaluasi relationship yang digunakan pada loop dan pertimbangkan:

$posts = Post::with('user')->get();

Kesalahan Umum: Terlalu Banyak Eager Loading

Kebalikan dari N+1 juga perlu diperhatikan.

Jangan melakukan:

Post::with([
    'user',
    'user.profile',
    'comments',
    'comments.user',
    'tags',
    'categories',
    'attachments',
    'likes',
])->get();

jika halaman sebenarnya hanya membutuhkan user dan tags.

Eager loading yang berlebihan dapat membuat query dan penggunaan memory meningkat.

Prinsipnya sederhana:

Load relationship yang memang dibutuhkan oleh use case tersebut.

Kesalahan Umum: Menganggap Relationship Selalu Mengembalikan Satu Object

hasOne() biasanya menghasilkan satu model atau null.

belongsTo() juga demikian.

Tetapi hasMany() dan belongsToMany() menghasilkan collection.

Contoh:

$user->profile;

berbeda dengan:

$user->posts;

posts dapat berisi banyak model.

Untuk collection:

foreach ($user->posts as $post) {
    // ...
}

Pemahaman ini penting agar tidak salah menggunakan property relationship.

Kesalahan Umum: Menghapus Data Parent Tanpa Memikirkan Child

Misalnya user memiliki banyak post.

Jika user dihapus, apa yang harus terjadi pada post?

Pilihan dapat berbeda berdasarkan kebutuhan:

User dihapus
↓
Posts ikut dihapus

atau:

User dihapus
↓
Posts tetap ada
↓
user_id menjadi NULL

Aturan tersebut sebaiknya ditentukan pada database dan migration.

Contoh:

->cascadeOnDelete();

atau:

->nullOnDelete();

Jangan memilih cascade hanya karena lebih mudah. Pastikan perilakunya sesuai dengan kebutuhan aplikasi.

Relationship dan Database Design Harus Konsisten

Eloquent Relationship bukan pengganti desain database.

Model:

public function posts(): HasMany
{
    return $this->hasMany(Post::class);
}

harus memiliki struktur database yang mendukung:

posts.user_id

Begitu pula Many to Many membutuhkan pivot table yang sesuai.

Karena itu, desain relationship sebaiknya dimulai dari pemahaman terhadap data:

Apa yang dimiliki?
Apa yang dimiliki oleh siapa?
Apakah satu atau banyak?
Apakah relationship membutuhkan atribut tambahan?

Setelah itu barulah migration dan model dibuat.

Contoh Struktur Blog Laravel

Untuk aplikasi blog sederhana, struktur relationship dapat berupa:

User
├── Profile
└── Posts
    ├── Comments
    └── Tags

Relationship-nya:

User
→ hasOne Profile

User
→ hasMany Posts

Post
→ belongsTo User

Post
→ hasMany Comments

Comment
→ belongsTo Post

Post
↔ belongsToMany Tags

Tag
↔ belongsToMany Posts

Dengan struktur tersebut, model dapat menjadi representasi yang jelas dari domain aplikasi.

Contoh Implementasi Model

Model User:

class User extends Authenticatable
{
    public function profile(): HasOne
    {
        return $this->hasOne(Profile::class);
    }

    public function posts(): HasMany
    {
        return $this->hasMany(Post::class);
    }
}

Model Post:

class Post extends Model
{
    protected $fillable = [
        'title',
        'content',
        'user_id',
    ];

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    public function comments(): HasMany
    {
        return $this->hasMany(Comment::class);
    }

    public function tags(): BelongsToMany
    {
        return $this->belongsToMany(Tag::class);
    }
}

Model Comment:

class Comment extends Model
{
    protected $fillable = [
        'content',
        'user_id',
        'post_id',
    ];

    public function post(): BelongsTo
    {
        return $this->belongsTo(Post::class);
    }

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }
}

Model Tag:

class Tag extends Model
{
    protected $fillable = [
        'name',
    ];

    public function posts(): BelongsToMany
    {
        return $this->belongsToMany(Post::class);
    }
}

Mengambil Data Blog dengan Relationship

Misalnya ingin menampilkan post beserta author, komentar, dan tag:

$posts = Post::with([
    'user',
    'comments.user',
    'tags',
])->latest()->get();

Kemudian pada view:

@foreach ($posts as $post)
    <h2>{{ $post->title }}</h2>

    <p>Author: {{ $post->user->name }}</p>

    @foreach ($post->tags as $tag)
        <span>{{ $tag->name }}</span>
    @endforeach
@endforeach

Relationship membuat kode view tetap mudah dipahami.

Kapan Sebaiknya Menggunakan Relationship?

Gunakan relationship ketika hubungan tersebut merupakan bagian nyata dari struktur data aplikasi.

Contohnya:

User → Profile

jika setiap user memiliki profile.

User → Posts

jika user dapat membuat banyak post.

Post ↔ Tags

jika post dan tag memiliki hubungan Many to Many.

Jangan membuat relationship hanya untuk mengurangi beberapa baris query. Relationship sebaiknya merepresentasikan hubungan domain dan database yang memang masuk akal.

Tips Merancang Relationship Laravel

Sebelum membuat relationship, tanyakan beberapa hal:

1. Siapa parent dan child?

Contoh:

User → Posts

User adalah parent, Post adalah child.

2. Berapa banyak record yang dapat dimiliki?

Jika satu:

hasOne()

Jika banyak:

hasMany()

3. Di mana foreign key berada?

Foreign key biasanya berada pada tabel yang memiliki hubungan belongsTo().

4. Apakah kedua sisi relationship perlu didefinisikan?

Sering kali iya.

Contohnya:

User → posts
Post → user

Dengan dua arah tersebut, navigasi data menjadi lebih fleksibel.

5. Apakah membutuhkan pivot table?

Jika:

A → banyak B
B → banyak A

kemungkinan besar membutuhkan Many to Many dengan pivot table.

Ringkasan Method Relationship

Sebagai referensi cepat:

MethodMaknaContoh
hasOne()Memiliki satuUser → Profile
belongsTo()Dimiliki olehPost → User
hasMany()Memiliki banyakUser → Posts
belongsToMany()Banyak ke banyakPost ↔ Tag

Kemudian beberapa method penting untuk mengambil relationship:

MethodKegunaan
with()Eager loading sebelum query
load()Eager loading setelah model tersedia
loadMissing()Load jika belum tersedia
has()Filter berdasarkan keberadaan relationship
whereHas()Filter relationship berdasarkan kondisi
whereDoesntHave()Mencari model tanpa relationship
withCount()Mengambil jumlah relationship
attach()Menambahkan Many to Many
detach()Menghapus Many to Many
sync()Menyinkronkan Many to Many
syncWithoutDetaching()Menambah tanpa melepas relationship lama

Kesimpulan

Laravel Eloquent Relationship membantu developer bekerja dengan data yang saling berhubungan tanpa harus menulis query database secara manual di setiap bagian aplikasi.

Konsep yang paling penting untuk dikuasai adalah:

  • One to One menggunakan hasOne() dan belongsTo().
  • One to Many menggunakan hasMany() dan belongsTo().
  • Many to Many menggunakan belongsToMany() dan pivot table.
  • Foreign key menentukan bagaimana tabel saling terhubung.
  • attach()detach(), dan sync() digunakan untuk mengelola Many to Many.
  • with() dan load() membantu mengontrol eager loading.
  • N+1 query problem perlu diperhatikan ketika mengakses relationship dalam loop.
  • has()whereHas(), dan withCount() berguna untuk query berdasarkan relationship.
  • Struktur database, migration, dan relationship pada model harus konsisten.

Jika konsep parent, child, foreign key, dan cardinality sudah dipahami, method Eloquent seperti hasMany()belongsTo(), dan belongsToMany() akan jauh lebih mudah dipahami.

Pada akhirnya, tujuan Eloquent Relationship bukan sekadar membuat query lebih pendek, tetapi membuat hubungan antar-data terlihat jelas di dalam kode aplikasi Laravel.