Eloquent, sebagai ORM (Object-Relational Mapper) bawaan Laravel, memudahkan interaksi kita dengan database. Salah satu kekuatan utama Eloquent adalah kemampuannya untuk mendefinisikan hubungan antar tabel, atau yang sering disebut relationship. Dalam tutorial ini, kita akan membahas secara mendalam tentang Laravel Eloquent Relationship Tutorial Bahasa Indonesia: Hubungan Antar Tabel, mulai dari dasar hingga contoh implementasi yang lebih kompleks. Jadi, siapkan kopi dan mari kita mulai!
1. Pengantar Hubungan Antar Tabel di Laravel Eloquent
Sebelum kita masuk ke kode, mari kita pahami dulu mengapa relationship itu penting. Bayangkan sebuah aplikasi blog. Setiap postingan (post) pasti memiliki seorang penulis (author). Setiap komentar (comment) pasti terhubung dengan sebuah postingan. Nah, relationship di Eloquent memungkinkan kita untuk mendefinisikan hubungan ini secara eksplisit dalam kode, sehingga kita bisa mengakses data terkait dengan mudah dan efisien.
Eloquent mendukung beberapa jenis hubungan utama:
- One To One: Satu model memiliki satu model terkait lainnya. (Contoh: Satu user memiliki satu profile)
- One To Many: Satu model memiliki banyak model terkait lainnya. (Contoh: Satu author memiliki banyak posts)
- Many To One (Inverse of One To Many): Banyak model mengacu pada satu model. (Contoh: Banyak posts mengacu pada satu author)
- Many To Many: Banyak model memiliki banyak model terkait lainnya melalui tabel perantara. (Contoh: Banyak users memiliki banyak roles)
- Has One Through: Satu model memiliki satu model lain melalui model perantara. (Contoh: Sebuah country bisa memiliki leader melalui user dan user_detail)
- Has Many Through: Satu model memiliki banyak model lain melalui model perantara. (Contoh: Sebuah country memiliki banyak posts melalui user dan user_detail)
- Polymorphic Relationships: Satu model dapat dimiliki oleh berbagai jenis model. (Contoh: Satu image bisa dimiliki oleh post, user, atau product)
2. Persiapan Database dan Model untuk Contoh Relationship
Sebelum kita mulai coding, pastikan kita sudah memiliki database dan model yang diperlukan. Kita akan menggunakan contoh sederhana: blog dengan model User (penulis) dan Post (postingan).
Langkah 1: Membuat Database
Buat sebuah database MySQL dengan nama blog. Sesuaikan konfigurasi database di file .env Laravel Anda:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=blog
DB_USERNAME=root
DB_PASSWORD=
Langkah 2: Membuat Migrasi dan Model User
Jalankan perintah berikut untuk membuat migrasi dan model User:
php artisan make:model User -m
Ini akan membuat file model di app/Models/User.php dan file migrasi di database/migrations. Edit file migrasi (database/migrations/..._create_users_table.php) seperti berikut:
<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('users');
}
};
Langkah 3: Membuat Migrasi dan Model Post
Lakukan hal yang sama untuk model Post:
php artisan make:model Post -m
Edit file migrasi (database/migrations/..._create_posts_table.php) seperti berikut:
<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id'); // Foreign Key ke tabel users
$table->string('title');
$table->text('content');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('posts');
}
};
Perhatikan penggunaan unsignedBigInteger('user_id') dan $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'). Ini mendefinisikan foreign key yang menghubungkan tabel posts dengan tabel users. onDelete('cascade') memastikan bahwa jika seorang user dihapus, semua postingannya juga akan dihapus.
Langkah 4: Menjalankan Migrasi
Jalankan migrasi untuk membuat tabel di database:
php artisan migrate
3. One To Many Relationship: User dan Post
Sekarang kita akan mendefinisikan hubungan One To Many antara User dan Post. Satu user (penulis) bisa memiliki banyak post.
Langkah 1: Mendefinisikan Relationship di Model User
Buka file app/Models/User.php dan tambahkan method posts() seperti berikut:
<?php
namespace AppModels;
use IlluminateFoundationAuthUser as Authenticatable;
use IlluminateNotificationsNotifiable;
use LaravelSanctumHasApiTokens;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
public function posts()
{
return $this->hasMany(Post::class);
}
}
Method posts() menggunakan hasMany() untuk mendefinisikan bahwa satu User memiliki banyak Post.
Langkah 2: Mendefinisikan Relationship di Model Post
Buka file app/Models/Post.php dan tambahkan method user() seperti berikut:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
class Post extends Model
{
use HasFactory;
protected $fillable = [
'user_id',
'title',
'content',
];
public function user()
{
return $this->belongsTo(User::class);
}
}
Method user() menggunakan belongsTo() untuk mendefinisikan bahwa satu Post dimiliki oleh satu User. Ini adalah kebalikan dari One To Many relationship dan sering disebut Many To One.
Langkah 3: Menggunakan Relationship untuk Mengambil Data
Sekarang kita bisa menggunakan relationship ini untuk mengambil data terkait. Misalnya, untuk mendapatkan semua postingan dari seorang user dengan ID 1:
$user = User::find(1);
$posts = $user->posts;
foreach ($posts as $post) {
echo $post->title . "<br>";
}
Atau, untuk mendapatkan user yang membuat sebuah post dengan ID 1:
$post = Post::find(1);
$user = $post->user;
echo $user->name;
4. Eager Loading: Meningkatkan Performa dengan Mengurangi Query
Secara default, saat kita mengakses relationship, Eloquent akan menjalankan query terpisah untuk setiap relationship. Ini bisa menyebabkan masalah performa, terutama jika kita memproses banyak data. Eager loading memungkinkan kita untuk mengambil semua data terkait dalam satu query, sehingga mengurangi jumlah query yang dijalankan.
Contoh:
Tanpa eager loading:
$posts = Post::all();
foreach ($posts as $post) {
echo $post->user->name . "<br>"; // Akan menjalankan query terpisah untuk setiap post
}
Dengan eager loading:
$posts = Post::with('user')->get(); // Mengambil semua user terkait dalam satu query
foreach ($posts as $post) {
echo $post->user->name . "<br>"; // Tidak menjalankan query terpisah
}
Perhatikan penggunaan with('user'). Ini memberitahu Eloquent untuk mengambil data user terkait saat mengambil data post. Ini secara signifikan meningkatkan performa, terutama jika kita memiliki banyak post.
Kita juga bisa eager load beberapa relationship sekaligus:
$posts = Post::with(['user', 'comments'])->get();
5. Lazy Eager Loading: Eager Loading Bersyarat
Terkadang, kita hanya ingin melakukan eager loading dalam kondisi tertentu. Lazy eager loading memungkinkan kita untuk menambahkan eager loading setelah query awal dijalankan.
Contoh:
$posts = Post::all();
if (kondisi_tertentu()) {
$posts->load('user');
}
foreach ($posts as $post) {
// Gunakan $post->user
}
6. Constraint Eager Loading: Memfilter Data yang Di-load
Kita bisa menambahkan constraint (batasan) ke query eager loading untuk memfilter data yang di-load.
Contoh:
$users = User::with(['posts' => function ($query) {
$query->where('title', 'like', '%Laravel%');
}])->get();
Ini akan mengambil semua user dan hanya post yang judulnya mengandung kata “Laravel”.
7. One To One Relationship: User dan Profile
Mari kita lihat contoh One To One relationship. Bayangkan setiap user memiliki satu profile.
Langkah 1: Membuat Migrasi dan Model Profile
php artisan make:model Profile -m
Edit file migrasi (database/migrations/..._create_profiles_table.php) seperti berikut:
<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('profiles', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id')->unique(); // Foreign Key ke tabel users, unique
$table->string('bio')->nullable();
$table->string('website')->nullable();
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('profiles');
}
};
Perhatikan unique() pada kolom user_id. Ini memastikan bahwa setiap user hanya memiliki satu profile.
Langkah 2: Mendefinisikan Relationship di Model User
Buka file app/Models/User.php dan tambahkan method profile() seperti berikut:
public function profile()
{
return $this->hasOne(Profile::class);
}
Langkah 3: Mendefinisikan Relationship di Model Profile
Buka file app/Models/Profile.php dan tambahkan method user() seperti berikut:
public function user()
{
return $this->belongsTo(User::class);
}
Langkah 4: Menggunakan Relationship untuk Mengambil Data
$user = User::find(1);
$profile = $user->profile;
echo $profile->bio;
$profile = Profile::find(1);
$user = $profile->user;
echo $user->name;
8. Many To Many Relationship: User dan Role
Mari kita lihat contoh Many To Many relationship. Bayangkan setiap user bisa memiliki banyak role (peran), dan setiap role bisa dimiliki oleh banyak user. Contoh: User “Admin” bisa memiliki role “Admin” dan “Editor”. User “Editor” bisa memiliki role “Editor”.
Langkah 1: Membuat Migrasi dan Model Role
php artisan make:model Role -m
Edit file migrasi (database/migrations/..._create_roles_table.php) seperti berikut:
<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('roles', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('roles');
}
};
Langkah 2: Membuat Migrasi Tabel Pivot role_user
Tabel pivot digunakan untuk menyimpan hubungan antara users dan roles. Buat migrasi untuk tabel pivot:
php artisan make:migration create_role_user_table
Edit file migrasi (database/migrations/..._create_role_user_table.php) seperti berikut:
<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('role_user', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('role_id');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
$table->unique(['user_id', 'role_id']); // Pastikan tidak ada duplikasi hubungan
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('role_user');
}
};
Langkah 3: Mendefinisikan Relationship di Model User
Buka file app/Models/User.php dan tambahkan method roles() seperti berikut:
public function roles()
{
return $this->belongsToMany(Role::class);
}
Langkah 4: Mendefinisikan Relationship di Model Role
Buka file app/Models/Role.php dan tambahkan method users() seperti berikut:
public function users()
{
return $this->belongsToMany(User::class);
}
Langkah 5: Menggunakan Relationship untuk Mengambil Data
$user = User::find(1);
$roles = $user->roles;
foreach ($roles as $role) {
echo $role->name . "<br>";
}
$role = Role::find(1);
$users = $role->users;
foreach ($users as $user) {
echo $user->name . "<br>";
}
Menambahkan Data ke Tabel Pivot
Untuk menambahkan role ke seorang user:
$user = User::find(1);
$role = Role::find(1);
$user->roles()->attach($role->id); // Menambahkan role ke user
Untuk menghapus role dari seorang user:
$user = User::find(1);
$role = Role::find(1);
$user->roles()->detach($role->id); // Menghapus role dari user
Untuk menambahkan beberapa role sekaligus:
$user = User::find(1);
$roleIds = [1, 2, 3]; // Array ID role yang ingin ditambahkan
$user->roles()->attach($roleIds);
9. Has One Through Relationship: Akses Data Melalui Tabel Perantara
Has One Through memungkinkan kita mengakses data dari tabel yang terhubung melalui tabel perantara. Misalnya, sebuah Country mungkin terhubung ke seorang Leader melalui tabel User dan UserDetails.
Langkah 1: Asumsi Struktur Database
Kita asumsikan struktur database berikut:
countries(id, name)users(id, country_id, name) – Ini bisa dianggap sebagai tabel perantarauser_details(id, user_id, is_leader) –is_leadermenandakan apakah user tersebut adalah leader
Langkah 2: Definisi Model
// app/Models/Country.php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Country extends Model
{
public function leader()
{
return $this->hasOneThrough(
User::class, // Model tujuan
UserDetails::class, // Model perantara
'country_id', // Foreign key pada tabel perantara (user_details)
'user_id', // Foreign key pada model tujuan (users)
'id', // Local key pada tabel countries
'id' // Local key pada tabel users
);
}
}
// app/Models/User.php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class User extends Model
{
// ...
}
// app/Models/UserDetails.php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class UserDetails extends Model
{
protected $table = 'user_details'; // Jika nama tabel berbeda
// ...
}
Langkah 3: Menggunakan Relationship
$country = Country::find(1);
$leader = $country->leader;
if ($leader) {
echo $leader->name;
} else {
echo "Negara ini tidak memiliki leader.";
}
10. Polymorphic Relationship: Hubungan Fleksibel dengan Berbagai Jenis Model
Polymorphic Relationships memungkinkan satu model untuk dimiliki oleh berbagai jenis model. Contoh: Sebuah gambar (image) bisa dimiliki oleh sebuah post, sebuah user, atau sebuah produk.
Langkah 1: Membuat Migrasi Tabel images
php artisan make:migration create_images_table
Edit file migrasi (database/migrations/..._create_images_table.php) seperti berikut:
<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('images', function (Blueprint $table) {
$table->id();
$table->string('url');
$table->morphs('imageable'); // Kolom untuk menyimpan ID dan tipe model yang memiliki image
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('images');
}
};
Perhatikan penggunaan $table->morphs('imageable'). Ini akan membuat dua kolom: imageable_id dan imageable_type. imageable_id menyimpan ID model yang memiliki image, dan imageable_type menyimpan nama kelas model tersebut (misalnya, AppModelsPost).
Langkah 2: Mendefinisikan Relationship di Model Image
Buat model Image:
php artisan make:model Image -m
Edit file app/Models/Image.php seperti berikut:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
class Image extends Model
{
use HasFactory;
public function imageable()
{
return $this->morphTo();
}
}
Langkah 3: Mendefinisikan Relationship di Model Post dan User
Di model Post:
public function images()
{
return $this->morphMany(Image::class, 'imageable');
}
Di model User:
public function images()
{
return $this->morphMany(Image::class, 'imageable');
}
Langkah 4: Menggunakan Relationship untuk Mengambil Data
$post = Post::find(1);
$images = $post->images;
foreach ($images as $image) {
echo $image->url . "<br>";
}
$image = Image::find(1);
$imageable = $image->imageable; // Mengembalikan model yang memiliki image (bisa Post, User, dll.)
if ($imageable instanceof Post) {
echo "Image ini dimiliki oleh sebuah Post: " . $imageable->title;
} elseif ($imageable instanceof User) {
echo "Image ini dimiliki oleh seorang User: " . $imageable->name;
}
11. Custom Keys: Menggunakan Kolom yang Berbeda Sebagai Kunci Asing
Secara default, Eloquent menganggap bahwa foreign key adalah nama model ditambah _id (misalnya, user_id untuk model User). Jika kita menggunakan kolom yang berbeda, kita bisa menentukan kunci asing secara eksplisit.
Contoh:
Jika tabel posts menggunakan kolom author_id sebagai foreign key ke tabel users:
// Di Model Post
public function user()
{
return $this->belongsTo(User::class, 'author_id'); // Menentukan 'author_id' sebagai foreign key
}
//Di Model User
public function posts()
{
return $this->hasMany(Post::class, 'author_id');
}
12. Kesimpulan: Memahami dan Memanfaatkan Laravel Eloquent Relationship Tutorial Bahasa Indonesia: Hubungan Antar Tabel
Dalam tutorial Laravel Eloquent Relationship Tutorial Bahasa Indonesia: Hubungan Antar Tabel ini, kita telah membahas berbagai jenis relationship yang didukung oleh Eloquent dan bagaimana cara menggunakannya. Memahami relationship adalah kunci untuk membangun aplikasi Laravel yang efisien dan mudah dipelihara. Dengan memanfaatkan relationship, kita bisa mengakses data terkait dengan mudah, mengurangi jumlah query yang dijalankan, dan meningkatkan performa aplikasi kita.
Jangan ragu untuk bereksperimen dengan berbagai jenis relationship dan constraint untuk menemukan solusi yang paling sesuai dengan kebutuhan aplikasi Anda. Selamat mencoba!

