Laravel Eloquent ORM (Object-Relational Mapper) adalah fitur yang sangat kuat yang mempermudah interaksi dengan database. Salah satu aspek penting dari Eloquent adalah relationships (hubungan antar tabel). Dalam artikel ini, kita akan membahas secara mendalam tentang One to Many Relationship (hubungan satu ke banyak) di Laravel Eloquent, lengkap dengan contoh kode dan penerapan praktisnya. Mari kita mulai!
Apa Itu Laravel Eloquent Relationship One to Many?
One to Many Relationship di Laravel Eloquent menggambarkan hubungan di mana satu model dapat memiliki banyak model terkait, tetapi setiap model terkait hanya dimiliki oleh satu model utama. Bayangkan sebuah blog: satu penulis (model User
) dapat memiliki banyak artikel (model Post
), tetapi setiap artikel hanya ditulis oleh satu penulis. Inilah esensi dari One to Many Relationship.
Dalam konteks database, ini biasanya diimplementasikan dengan foreign key (kunci asing) di tabel “anak” (misalnya, tabel posts
) yang menunjuk ke primary key (kunci utama) di tabel “induk” (misalnya, tabel users
).
Konsep Dasar Foreign Key dan Primary Key dalam Hubungan One to Many
Sebelum melangkah lebih jauh, mari kita pahami dulu peran kunci asing (foreign key) dan kunci utama (primary key) dalam membangun hubungan One to Many.
- Primary Key (Kunci Utama): Ini adalah kolom yang secara unik mengidentifikasi setiap baris dalam tabel. Biasanya, ini adalah kolom
id
yang menggunakan auto-increment. - Foreign Key (Kunci Asing): Ini adalah kolom di tabel anak yang mereferensikan primary key dari tabel induk. Kolom ini menunjukkan bahwa baris ini terkait dengan baris tertentu di tabel induk. Dalam contoh penulis dan artikel, tabel
posts
akan memiliki kolomuser_id
sebagai foreign key yang menunjuk ke kolomid
di tabelusers
.
Membuat Migrasi dan Model untuk Hubungan One to Many
Sekarang, mari kita buat migrasi dan model yang diperlukan untuk contoh penulis dan artikel.
1. Membuat Migrasi untuk Tabel users
(Penulis):
php artisan make:migration create_users_table --create=users
Buka file migrasi yang baru dibuat (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');
}
};
2. Membuat Migrasi untuk Tabel posts
(Artikel):
php artisan make:migration create_posts_table --create=posts
Buka file migrasi yang baru dibuat 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('body');
$table->unsignedBigInteger('user_id'); // Foreign Key
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); // Menentukan hubungan dan cascading delete
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('posts');
}
};
Perhatikan bagian unsignedBigInteger('user_id')
dan $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
. Inilah yang mendefinisikan foreign key dan hubungannya dengan tabel users
. onDelete('cascade')
berarti jika seorang penulis dihapus, semua artikelnya juga akan dihapus secara otomatis.
3. Membuat Model User
:
Model ini mungkin sudah ada jika Anda menggunakan autentikasi bawaan Laravel. Jika belum, buat dengan perintah:
php artisan make:model User
4. Membuat Model Post
:
php artisan make:model Post
Mendefinisikan Relationship One to Many di Model
Sekarang, kita perlu mendefinisikan hubungan One to Many di dalam model User
dan Post
.
1. Mendefinisikan Relationship di Model User
(Penulis):
Buka file app/Models/User.php
dan tambahkan fungsi posts()
:
<?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',
];
/**
* Get all of the posts for the User
*
* @return IlluminateDatabaseEloquentRelationsHasMany
*/
public function posts(): HasMany
{
return $this->hasMany(Post::class);
}
}
Fungsi posts()
menggunakan method hasMany()
. Method ini memberitahu Eloquent bahwa model User
memiliki banyak model Post
.
2. Mendefinisikan Relationship di Model Post
(Artikel):
Buka file app/Models/Post.php
dan tambahkan fungsi user()
:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
use IlluminateDatabaseEloquentRelationsBelongsTo;
class Post extends Model
{
use HasFactory;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'title',
'body',
'user_id',
];
/**
* Get the user that owns the Post
*
* @return IlluminateDatabaseEloquentRelationsBelongsTo
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}
Fungsi user()
menggunakan method belongsTo()
. Method ini memberitahu Eloquent bahwa model Post
termasuk (belongs to) satu model User
.
Penting: Pastikan Anda telah menjalankan migrasi dengan perintah php artisan migrate
untuk membuat tabel di database.
Contoh Penggunaan Relationship One to Many
Sekarang, mari kita lihat beberapa contoh bagaimana kita bisa menggunakan relationship One to Many yang telah kita definisikan.
1. Mengambil Semua Artikel Seorang Penulis (Eager Loading):
$user = User::with('posts')->find(1); // Mengambil User dengan ID 1 beserta semua Post-nya
if ($user) {
echo "Penulis: " . $user->name . "<br>";
echo "Daftar Artikel:<br>";
foreach ($user->posts as $post) {
echo "- " . $post->title . "<br>";
}
} else {
echo "Penulis tidak ditemukan.";
}
Kode di atas menggunakan eager loading (with('posts')
) untuk mengambil semua artikel (posts) dari penulis (user) dengan ID 1 dalam satu query database. Ini lebih efisien daripada lazy loading karena menghindari masalah N+1 query.
2. Mengakses Penulis dari Sebuah Artikel:
$post = Post::find(1); // Mengambil Post dengan ID 1
if ($post) {
echo "Judul Artikel: " . $post->title . "<br>";
echo "Penulis: " . $post->user->name . "<br>"; // Mengakses nama penulis melalui relationship
} else {
echo "Artikel tidak ditemukan.";
}
Kode ini menunjukkan bagaimana kita bisa mengakses informasi penulis dari sebuah artikel menggunakan relationship user()
.
3. Membuat Artikel Baru untuk Seorang Penulis:
$user = User::find(1); // Mengambil User dengan ID 1
if ($user) {
$post = new Post();
$post->title = "Artikel Baru";
$post->body = "Isi artikel baru...";
$user->posts()->save($post); // Menyimpan artikel baru melalui relationship
echo "Artikel baru berhasil dibuat untuk penulis " . $user->name;
} else {
echo "Penulis tidak ditemukan.";
}
Perhatikan penggunaan $user->posts()->save($post)
. Ini adalah cara yang tepat untuk membuat dan mengaitkan artikel baru dengan seorang penulis. Eloquent akan secara otomatis mengisi kolom user_id
dengan ID penulis yang bersangkutan.
4. Membuat Beberapa Artikel Baru Sekaligus untuk Seorang Penulis:
$user = User::find(1);
if ($user) {
$posts = [
new Post(['title' => 'Artikel Satu', 'body' => 'Isi Artikel Satu']),
new Post(['title' => 'Artikel Dua', 'body' => 'Isi Artikel Dua']),
];
$user->posts()->saveMany($posts);
echo "Beberapa artikel baru berhasil dibuat untuk penulis " . $user->name;
} else {
echo "Penulis tidak ditemukan.";
}
Kode ini menggunakan saveMany()
untuk menyimpan beberapa artikel sekaligus, lebih efisien daripada memanggil save()
berkali-kali.
5. Mendapatkan Jumlah Artikel yang Dimiliki Seorang Penulis:
$user = User::find(1);
if ($user) {
$jumlahArtikel = $user->posts()->count();
echo "Penulis " . $user->name . " memiliki " . $jumlahArtikel . " artikel.";
} else {
echo "Penulis tidak ditemukan.";
}
Method count()
memungkinkan kita untuk menghitung jumlah artikel yang terkait dengan seorang penulis dengan mudah.
Advanced: Custom Foreign Key dan Local Key
Secara default, Eloquent menganggap bahwa foreign key adalah nama model induk diikuti dengan _id
(misalnya, user_id
untuk model User
). Dan local key (primary key di tabel induk) adalah id
.
Namun, Anda bisa menyesuaikan foreign key dan local key jika diperlukan.
Contoh:
Katakanlah, dalam tabel posts
, foreign key untuk user
adalah author_id
dan primary key di tabel users
adalah user_code
. Maka, definisi relationship di model Post
akan menjadi:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
use IlluminateDatabaseEloquentRelationsBelongsTo;
class Post extends Model
{
use HasFactory;
/**
* Get the user that owns the Post
*
* @return IlluminateDatabaseEloquentRelationsBelongsTo
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'author_id', 'user_code'); // Custom foreign key dan local key
}
}
Dan definisi di model User
akan menjadi:
<?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;
/**
* Get all of the posts for the User
*
* @return IlluminateDatabaseEloquentRelationsHasMany
*/
public function posts(): HasMany
{
return $this->hasMany(Post::class, 'author_id', 'user_code');
}
}
Anda memberikan foreign key (author_id
) dan local key (user_code
) sebagai argumen kedua dan ketiga ke method belongsTo()
dan hasMany()
.
Tips dan Trik Optimasi Query One to Many Relationship
- Eager Loading: Selalu gunakan eager loading (misalnya,
User::with('posts')->get()
) untuk menghindari masalah N+1 query. - Select Columns: Gunakan
select()
untuk hanya mengambil kolom yang Anda butuhkan. Ini mengurangi jumlah data yang diambil dari database dan mempercepat query. Contoh:User::with(['posts' => function ($query) { $query->select('id', 'title', 'user_id'); }])->get(['id', 'name']);
- Caching: Pertimbangkan untuk menggunakan caching untuk data yang jarang berubah, seperti daftar kategori atau konfigurasi aplikasi.
- Indexing: Pastikan Anda memiliki indeks yang tepat pada kolom foreign key untuk mempercepat pencarian.
Kesimpulan
Laravel Eloquent Relationship One to Many adalah alat yang sangat berguna untuk membangun aplikasi web yang kompleks dan terstruktur. Dengan memahami konsep dasar dan penerapan praktisnya, Anda dapat mengelola data dengan lebih efisien dan meningkatkan performa aplikasi Anda. Ingatlah untuk selalu menggunakan eager loading, memilih kolom yang relevan, dan mempertimbangkan caching untuk mengoptimalkan query Anda. Selamat mencoba!
Sumber Terpercaya: