Laravel Eloquent ORM mempermudah interaksi dengan database. Salah satu fitur terkuatnya adalah kemampuannya untuk mendefinisikan relationships antar tabel. Dalam artikel ini, kita akan membahas secara mendalam tentang one-to-many relationship di Laravel Eloquent, lengkap dengan contoh praktis dan kode yang mudah dipahami. Kita akan melihat bagaimana relationship ini bekerja, cara mendefinisikannya, dan bagaimana menggunakannya untuk mengambil dan memanipulasi data. Siap? Mari kita mulai!
1. Memahami Konsep One-to-Many Relationship di Eloquent
Apa sebenarnya yang dimaksud dengan one-to-many relationship? Sederhananya, ini adalah hubungan di mana satu entitas di satu tabel dapat memiliki banyak entitas terkait di tabel lain. Contoh klasik adalah relasi antara User
dan Post
. Satu user (pengguna) dapat memiliki banyak post (artikel), tetapi setiap post hanya dimiliki oleh satu user.
Bayangkan sebuah blog. Setiap penulis (user) dapat menulis banyak artikel (post), tetapi setiap artikel hanya ditulis oleh satu penulis. Ini adalah contoh sempurna dari one-to-many relationship. Di database, ini biasanya direpresentasikan dengan kolom foreign key di tabel posts
yang menunjuk ke kolom primary key di tabel users
.
Berikut beberapa contoh lain yang sering ditemui:
- Category dan Product: Satu kategori dapat memiliki banyak produk.
- Order dan OrderItem: Satu order dapat berisi banyak item pesanan.
- Author dan Book: Satu penulis dapat menulis banyak buku.
Memahami konsep ini adalah kunci sebelum kita melangkah lebih jauh ke implementasi kode di Laravel Eloquent.
2. Persiapan Database: Membuat Migrasi dan Model untuk Relationship
Sebelum kita bisa mendefinisikan relationship di Eloquent, kita perlu menyiapkan database dan model kita. Mari kita gunakan contoh User
dan Post
seperti di atas.
Langkah 1: Membuat Migrasi untuk Tabel users
dan posts
Jalankan perintah berikut di terminal untuk membuat file migrasi:
php artisan make:migration create_users_table
php artisan make:migration create_posts_table
Buka file migrasi create_users_table
(biasanya terletak di database/migrations
) dan tambahkan kode 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');
}
};
Kemudian, buka file migrasi create_posts_table
dan tambahkan kode 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->string('title');
$table->text('content');
$table->foreignId('user_id')->constrained()->onDelete('cascade'); // Foreign Key
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('posts');
}
};
Penjelasan:
$table->foreignId('user_id')->constrained()->onDelete('cascade');
: Ini adalah bagian terpenting. Kita membuat kolomuser_id
sebagai foreign key yang menunjuk ke tabelusers
.constrained()
: Menambahkan index dan constraint ke foreign key.onDelete('cascade')
: Jika user dihapus, semua post yang terkait dengan user tersebut juga akan dihapus (cascade delete). Ini memastikan integritas data.
Langkah 2: Menjalankan Migrasi
Jalankan perintah berikut untuk membuat tabel di database:
php artisan migrate
Langkah 3: Membuat Model User
dan Post
Jalankan perintah berikut untuk membuat model:
php artisan make:model User
php artisan make:model Post
Ini akan membuat file User.php
dan Post.php
di direktori app/Models
.
3. Mendefinisikan HasMany
Relationship di Model User
Sekarang, kita akan mendefinisikan one-to-many relationship di model User
. Buka file app/Models/User.php
dan tambahkan metode posts()
seperti berikut:
<?php
namespace AppModels;
use IlluminateContractsAuthMustVerifyEmail;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateFoundationAuthUser as Authenticatable;
use IlluminateNotificationsNotifiable;
use LaravelSanctumHasApiTokens;
use IlluminateDatabaseEloquentRelationsHasMany;
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',
];
/**
* Get all of the posts for the User
*
* @return IlluminateDatabaseEloquentRelationsHasMany
*/
public function posts(): HasMany
{
return $this->hasMany(Post::class);
}
}
Penjelasan:
public function posts(): HasMany
: Kita mendefinisikan sebuah metode bernamaposts
yang mengembalikan instance dariHasMany
.$this->hasMany(Post::class)
: Ini memberitahu Eloquent bahwa modelUser
memiliki manyPost
.Post::class
menentukan model yang terkait dengan relationship ini.
Dengan kode ini, kita telah mendefinisikan bahwa setiap User
dapat memiliki banyak Post
.
4. Mendefinisikan BelongsTo
Relationship di Model Post
Selanjutnya, kita perlu mendefinisikan sisi lain dari relationship ini di model Post
. Buka file app/Models/Post.php
dan tambahkan metode user()
seperti berikut:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
use IlluminateDatabaseEloquentRelationsBelongsTo;
class Post extends Model
{
use HasFactory;
protected $fillable = ['title', 'content', 'user_id']; // Penting untuk mass assignment
/**
* Get the user that owns the Post
*
* @return IlluminateDatabaseEloquentRelationsBelongsTo
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}
Penjelasan:
public function user(): BelongsTo
: Kita mendefinisikan sebuah metode bernamauser
yang mengembalikan instance dariBelongsTo
.$this->belongsTo(User::class)
: Ini memberitahu Eloquent bahwa modelPost
belongs to modelUser
.
Dengan kode ini, kita telah mendefinisikan bahwa setiap Post
dimiliki oleh satu User
. Perhatikan juga $fillable
. Ini penting agar kita bisa melakukan mass assignment saat membuat post baru (akan dibahas di bagian selanjutnya).
5. Contoh Kode: Mengambil Data Menggunakan One-to-Many Relationship
Setelah mendefinisikan relationship, mari kita lihat bagaimana cara menggunakan relationship ini untuk mengambil data.
Contoh 1: Mengambil Semua Post Milik Seorang User
use AppModelsUser;
$user = User::find(1); // Ambil user dengan ID 1
if ($user) {
$posts = $user->posts; // Akses relasi posts melalui properti dinamis
foreach ($posts as $post) {
echo "Judul: " . $post->title . "<br>";
echo "Konten: " . $post->content . "<br>";
echo "<br>";
}
} else {
echo "User tidak ditemukan.";
}
Penjelasan:
$user->posts
: Ini adalah cara paling mudah untuk mengakses semua post yang dimiliki oleh user. Eloquent secara otomatis menjalankan query untuk mengambil semua post yang memilikiuser_id
sama dengan ID user.- Kita mengiterasi melalui
$posts
untuk menampilkan judul dan konten setiap post.
Contoh 2: Mengambil User yang Memiliki Sebuah Post
use AppModelsPost;
$post = Post::find(1); // Ambil post dengan ID 1
if ($post) {
$user = $post->user; // Akses relasi user melalui properti dinamis
echo "Nama User: " . $user->name . "<br>";
echo "Email User: " . $user->email . "<br>";
} else {
echo "Post tidak ditemukan.";
}
Penjelasan:
$post->user
: Ini adalah cara mudah untuk mengakses user yang memiliki post. Eloquent secara otomatis menjalankan query untuk mengambil user berdasarkanuser_id
di tabelposts
.
6. Eager Loading: Meningkatkan Performa Query
Secara default, Eloquent menggunakan lazy loading. Artinya, relationship baru dimuat ketika Anda pertama kali mengaksesnya (seperti saat kita mengakses $user->posts
). Ini bisa menyebabkan masalah performa jika Anda perlu mengakses relationship untuk banyak model. Solusinya adalah menggunakan eager loading.
Contoh: Eager Loading Relationship posts
saat Mengambil User
use AppModelsUser;
$users = User::with('posts')->get(); // Eager load relationship 'posts'
foreach ($users as $user) {
echo "Nama User: " . $user->name . "<br>";
echo "Jumlah Post: " . $user->posts->count() . "<br>"; // Tidak ada query tambahan untuk setiap user
echo "<br>";
}
Penjelasan:
User::with('posts')->get()
: Dengan menggunakanwith('posts')
, kita memberitahu Eloquent untuk mengambil semua post terkait dengan setiap user dalam satu query. Ini mengurangi jumlah query yang dieksekusi secara signifikan.$user->posts->count()
: Kita bisa mengakses collection$posts
untuk setiap user tanpa memicu query database tambahan.
Eager loading sangat penting untuk menjaga aplikasi Anda tetap cepat dan responsif, terutama ketika Anda bekerja dengan data yang memiliki relationships kompleks.
7. Menyimpan Data: Membuat Post Baru untuk Seorang User
Sekarang, mari kita lihat bagaimana cara membuat post baru yang terkait dengan seorang user.
Contoh:
use AppModelsUser;
use AppModelsPost;
$user = User::find(1); // Ambil user dengan ID 1
if ($user) {
$post = new Post([
'title' => 'Judul Post Baru',
'content' => 'Konten Post Baru',
]);
$user->posts()->save($post); // Buat post baru terkait dengan user
echo "Post berhasil dibuat!";
} else {
echo "User tidak ditemukan.";
}
Penjelasan:
$user->posts()->save($post)
: Ini adalah cara paling aman dan direkomendasikan untuk membuat post baru yang terkait dengan seorang user.- Kita membuat instance
Post
baru. - Kita menggunakan metode
posts()
dari modelUser
untuk mendapatkan instance dari relationshipHasMany
. - Kita menggunakan metode
save()
pada instance relationship untuk menyimpan post baru. Ini secara otomatis mengaturuser_id
pada post dengan ID user.
- Kita membuat instance
Alternatif dengan create()
(Hati-hati dengan Mass Assignment):
Anda juga bisa menggunakan metode create()
:
use AppModelsUser;
$user = User::find(1);
if ($user) {
$post = $user->posts()->create([
'title' => 'Judul Post Baru',
'content' => 'Konten Post Baru',
]);
echo "Post berhasil dibuat!";
} else {
echo "User tidak ditemukan.";
}
Penting: Mass Assignment!
Perhatikan bahwa jika Anda menggunakan create()
, Anda harus memastikan bahwa atribut title
dan content
diizinkan untuk mass assignment di model Post
. Ini dilakukan dengan menambahkan atribut $fillable
ke model Post
:
// app/Models/Post.php
protected $fillable = ['title', 'content', 'user_id']; // user_id juga perlu dimasukkan jika anda ingin mass assign secara manual.
Jika Anda tidak menambahkan atribut $fillable
, Anda akan mendapatkan error MassAssignmentException. Alternatif lain adalah menggunakan $guarded
untuk menentukan atribut yang tidak boleh di-mass assign.
8. Updating Data: Mengubah Data Post Milik Seorang User
Berikut adalah contoh cara mengupdate data post yang terkait dengan user:
use AppModelsUser;
$user = User::find(1);
if($user){
$post = $user->posts()->find(1); // Mengambil post pertama milik user
if($post){
$post->title = "Judul Post yang Diperbarui";
$post->content = "Konten Post yang Diperbarui";
$post->save();
echo "Post berhasil diupdate!";
} else {
echo "Post tidak ditemukan.";
}
} else {
echo "User tidak ditemukan.";
}
Penjelasan:
- Mencari User: Pertama, kita mencari user dengan ID 1.
- Mencari Post Milik User: Kita menggunakan
$user->posts()->find(1)
untuk mencari post dengan ID 1 yang dimiliki oleh user tersebut. Ini memastikan kita hanya mengupdate post yang memang dimiliki oleh user yang benar. - Mengupdate Data: Jika post ditemukan, kita mengubah
title
dancontent
post. - Menyimpan Perubahan: Kita menggunakan
$post->save()
untuk menyimpan perubahan ke database.
9. Menghapus Data: Menghapus Post Milik Seorang User
Berikut adalah contoh cara menghapus data post yang terkait dengan user:
use AppModelsUser;
$user = User::find(1);
if($user){
$post = $user->posts()->find(1); // Mengambil post pertama milik user
if($post){
$post->delete();
echo "Post berhasil dihapus!";
} else {
echo "Post tidak ditemukan.";
}
} else {
echo "User tidak ditemukan.";
}
Penjelasan:
Prosesnya mirip dengan updating:
- Mencari User dan Post: Kita mencari user dan kemudian mencari post milik user tersebut.
- Menghapus Post: Jika post ditemukan, kita menggunakan
$post->delete()
untuk menghapus post dari database. Karena kita menggunakanonDelete('cascade')
pada foreign key, semua post yang terkait dengan user akan dihapus jika user tersebut dihapus.
10. Customizing the Keys: Mengubah Nama Foreign Key dan Local Key
Secara default, Eloquent mengasumsikan nama foreign key dan local key berdasarkan nama model. Namun, Anda dapat mengkustomisasi ini jika nama kolom Anda berbeda.
Contoh:
Misalkan kolom foreign key di tabel posts
bernama author_id
bukan user_id
. Anda dapat mendefinisikan relationship dengan cara berikut:
// app/Models/User.php
public function posts(): HasMany
{
return $this->hasMany(Post::class, 'author_id'); // Menentukan nama foreign key
}
// app/Models/Post.php
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'author_id'); //Menentukan nama foreign key di model Post.
}
Jika kolom primary key di tabel users
bukan id
, Anda dapat mendefinisikan relationship dengan cara berikut:
// app/Models/User.php
public function posts(): HasMany
{
return $this->hasMany(Post::class, 'author_id', 'custom_id'); // Menentukan nama foreign key dan local key
}
// app/Models/Post.php
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'author_id', 'custom_id'); // Menentukan nama foreign key dan local key
}
Ganti custom_id
dengan nama kolom primary key Anda. Penting untuk konsisten dalam menentukan nama foreign key dan local key di kedua sisi relationship.
11. Querying Relationships: Menggunakan whereHas
untuk Menyaring Hasil
Terkadang, Anda ingin mengambil user yang memiliki post dengan kondisi tertentu. Anda dapat menggunakan metode whereHas
untuk melakukan ini.
Contoh: Mengambil Semua User yang Memiliki Post dengan Judul Mengandung Kata “Berita”
use AppModelsUser;
$users = User::whereHas('posts', function ($query) {
$query->where('title', 'like', '%Berita%');
})->get();
foreach ($users as $user) {
echo "Nama User: " . $user->name . "<br>";
}
Penjelasan:
User::whereHas('posts', function ($query) { ... })
: Ini memberitahu Eloquent untuk hanya mengambil user yang memiliki relationshipposts
yang memenuhi kondisi tertentu.$query->where('title', 'like', '%Berita%')
: Ini menentukan kondisi yang harus dipenuhi oleh relationshipposts
. Dalam hal ini, kita mencari post yang judulnya mengandung kata “Berita”.
12. Kesimpulan: Manfaat dan Penggunaan Laravel Eloquent One-to-Many Relationship
Laravel Eloquent one-to-many relationship adalah alat yang sangat kuat untuk memodelkan hubungan antar data di aplikasi Anda. Dengan memahami konsep dan contoh kode yang telah kita bahas, Anda dapat dengan mudah mengelola data yang kompleks dan meningkatkan performa aplikasi Anda. Ingatlah untuk selalu mempertimbangkan penggunaan eager loading dan mass assignment untuk optimasi dan keamanan. Dengan menggunakan relationship Eloquent, Anda dapat menulis kode yang lebih bersih, lebih mudah dibaca, dan lebih mudah dipelihara. Selamat mencoba!