Laravel Eloquent ORM adalah kekuatan utama di balik kemudahan berinteraksi dengan database dalam aplikasi Laravel. Salah satu fitur paling berguna dari Eloquent adalah kemampuannya untuk mendefinisikan relasi antar tabel database. Artikel ini akan membahas secara mendalam tentang relasi one-to-many (satu-ke-banyak) di Laravel Eloquent, lengkap dengan contoh kode dan penjelasan yang mudah dipahami. Jadi, mari kita mulai perjalanan kita untuk memahami relasi one-to-many di Laravel!
Apa itu Relasi One-to-Many di Laravel Eloquent?
Relasi one-to-many (satu-ke-banyak) adalah jenis relasi database di mana satu baris di tabel A berhubungan dengan banyak baris di tabel B. Contoh klasiknya adalah relasi antara penulis (Author) dan postingan (Post). Seorang penulis dapat memiliki banyak postingan, tetapi setiap postingan hanya dimiliki oleh satu penulis.
Dalam konteks Laravel Eloquent, ini berarti satu model (misalnya, Author
) dapat memiliki banyak model lain (misalnya, Post
). Kita akan mendefinisikan relasi ini di dalam model Eloquent kita sehingga kita dapat dengan mudah mengambil dan memanipulasi data yang terkait.
Struktur Database untuk Relasi One-to-Many: Studi Kasus Penulis dan Postingan
Sebelum kita masuk ke kode, penting untuk memahami struktur database yang dibutuhkan untuk relasi one-to-many. Mari kita gunakan contoh penulis dan postingan. Kita akan memerlukan dua tabel:
- authors: Menyimpan informasi tentang penulis. Kolom-kolomnya mungkin mencakup
id
,name
,email
, dancreated_at
/updated_at
. - posts: Menyimpan informasi tentang postingan. Kolom-kolomnya mungkin mencakup
id
,author_id
,title
,body
, dancreated_at
/updated_at
.
Kunci penting di sini adalah kolom author_id
di tabel posts
. Kolom ini adalah foreign key yang menunjuk ke id
di tabel authors
. Ini adalah penghubung yang membangun relasi one-to-many. Setiap postingan memiliki author_id
yang menunjukkan siapa penulisnya.
Berikut adalah contoh migration untuk membuat tabel-tabel ini:
// database/migrations/xxxx_xx_xx_create_authors_table.php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
class CreateAuthorsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('authors', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('authors');
}
}
// database/migrations/xxxx_xx_xx_create_posts_table.php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
class CreatePostsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('author_id');
$table->string('title');
$table->text('body');
$table->timestamps();
$table->foreign('author_id')->references('id')->on('authors')->onDelete('cascade'); // Penting untuk foreign key constraint
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
}
Penjelasan Kode Migration:
Schema::create('authors', function (Blueprint $table) { ... });
Membuat tabel bernamaauthors
.$table->id();
Membuat kolomid
sebagai primary key (auto-incrementing integer).$table->string('name');
Membuat kolomname
bertipe string.$table->string('email')->unique();
Membuat kolomemail
bertipe string dan memastikan nilainya unik.$table->timestamps();
Membuat kolomcreated_at
danupdated_at
untuk mencatat waktu pembuatan dan pembaruan data.$table->unsignedBigInteger('author_id');
Membuat kolomauthor_id
sebagai unsigned big integer (sesuai dengan tipe dataid
di tabelauthors
).$table->text('body');
Membuat kolombody
bertipe text (untuk menyimpan konten postingan yang lebih panjang).$table->foreign('author_id')->references('id')->on('authors')->onDelete('cascade');
Ini adalah kunci! Ini mendefinisikan foreign key constraint. Ini berarti:$table->foreign('author_id')
:author_id
adalah foreign key.references('id')
:author_id
merujuk ke kolomid
di tabel…on('authors')
: …tabelauthors
.onDelete('cascade')
: Ini sangat penting! Jika seorang penulis dihapus (didelete), semua postingan yang terkait dengan penulis tersebut juga akan dihapus secara otomatis. Ini memastikan integritas data. Pilihan lain adalahonDelete('set null')
, yang akan mengaturauthor_id
di postingan menjadiNULL
jika penulis dihapus.
Setelah membuat migration, jalankan php artisan migrate
untuk membuat tabel di database Anda.
Mendefinisikan Relasi di Model Eloquent: HasMany dan BelongsTo
Sekarang kita memiliki struktur database yang benar, kita perlu mendefinisikan relasi di model Eloquent kita. Kita akan memiliki dua model: Author
dan Post
.
// app/Models/Author.php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
class Author extends Model
{
use HasFactory;
protected $fillable = ['name', 'email']; // Kolom yang boleh diisi
public function posts()
{
return $this->hasMany(Post::class);
}
}
// app/Models/Post.php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
class Post extends Model
{
use HasFactory;
protected $fillable = ['author_id', 'title', 'body']; // Kolom yang boleh diisi
public function author()
{
return $this->belongsTo(Author::class);
}
}
Penjelasan Kode Model:
$fillable = ['name', 'email'];
(di modelAuthor
) dan$fillable = ['author_id', 'title', 'body'];
(di modelPost
) adalah mass assignment protection. Ini menentukan kolom mana yang boleh diisi ketika kita membuat atau memperbarui model menggunakan array. Penting untuk melindungi aplikasi Anda dari kerentanan mass assignment.public function posts()
(di modelAuthor
): Ini mendefinisikan relasi one-to-many dari perspektif penulis. Ini menggunakan methodhasMany()
.return $this->hasMany(Post::class);
Ini berarti: “Seorang penulis memiliki banyak postingan.”- Parameter
Post::class
menunjukkan model yang terkait (dalam hal ini,Post
).
public function author()
(di modelPost
): Ini mendefinisikan relasi kebalikan dari perspektif postingan. Ini menggunakan methodbelongsTo()
.return $this->belongsTo(Author::class);
Ini berarti: “Sebuah postingan termasuk ke seorang penulis.”- Parameter
Author::class
menunjukkan model yang terkait (dalam hal ini,Author
).
Penting: Eloquent secara otomatis mengasumsikan bahwa kolom foreign key di tabel posts
adalah author_id
(nama model Author
dalam snake case diikuti dengan _id
). Jika Anda menggunakan nama kolom yang berbeda, Anda perlu menentukannya sebagai parameter kedua di method hasMany()
dan belongsTo()
. Misalnya, jika kolom foreign key Anda bernama penulis_id
, Anda akan menggunakan:
// app/Models/Author.php
public function posts()
{
return $this->hasMany(Post::class, 'penulis_id');
}
// app/Models/Post.php
public function author()
{
return $this->belongsTo(Author::class, 'penulis_id');
}
Contoh Kode Penggunaan Relasi One-to-Many
Sekarang kita telah mendefinisikan relasi, mari kita lihat beberapa contoh cara menggunakannya:
1. Mengambil Semua Postingan dari Seorang Penulis:
$author = Author::find(1); // Misalnya, ambil penulis dengan ID 1
$posts = $author->posts; // Mengakses relasi "posts"
foreach ($posts as $post) {
echo $post->title . "<br>";
}
Kode ini pertama-tama mengambil penulis dengan ID 1. Kemudian, ia mengakses relasi posts
melalui properti $author->posts
. Ini mengembalikan collection dari semua model Post
yang terkait dengan penulis tersebut. Kita kemudian dapat melakukan iterasi melalui collection ini untuk mengakses atribut postingan.
2. Mengambil Penulis dari Sebuah Postingan:
$post = Post::find(5); // Misalnya, ambil postingan dengan ID 5
$author = $post->author; // Mengakses relasi "author"
echo $author->name;
Kode ini mengambil postingan dengan ID 5. Kemudian, ia mengakses relasi author
melalui properti $post->author
. Ini mengembalikan model Author
yang memiliki postingan tersebut.
3. Membuat Postingan Baru untuk Seorang Penulis:
$author = Author::find(1);
$post = new Post([
'title' => 'Judul Postingan Baru',
'body' => 'Isi postingan baru...'
]);
$author->posts()->save($post); // Menggunakan method "save" untuk relasi
Kode ini pertama-tama mengambil penulis dengan ID 1. Kemudian, ia membuat instance baru dari model Post
dan mengisi atribut title
dan body
. Yang penting di sini adalah kita menggunakan method save()
pada relasi posts()
daripada memanggil save()
langsung pada model Post
. Ini secara otomatis akan mengatur author_id
di postingan ke ID penulis.
Alternatif yang lebih ringkas menggunakan create()
:
$author = Author::find(1);
$author->posts()->create([
'title' => 'Judul Postingan Baru',
'body' => 'Isi postingan baru...'
]);
Method create()
melakukan hal yang sama seperti save()
tetapi lebih ringkas karena tidak memerlukan pembuatan instance model Post
secara manual.
4. Eager Loading: Meningkatkan Performa dengan Mengurangi Query Database
Secara default, saat Anda mengakses relasi, Eloquent akan menjalankan query database terpisah untuk setiap relasi. Ini bisa menjadi masalah performa jika Anda memuat banyak model dan relasi. Eager loading memungkinkan Anda untuk memuat relasi bersama dengan model utama dalam satu query database, secara signifikan mengurangi jumlah query.
$authors = Author::with('posts')->get(); // Eager load relasi "posts"
foreach ($authors as $author) {
echo $author->name . "<br>";
foreach ($author->posts as $post) {
echo "- " . $post->title . "<br>";
}
}
Kode ini menggunakan method with('posts')
untuk menentukan bahwa kita ingin memuat relasi posts
bersama dengan model Author
. Ini berarti hanya ada dua query database: satu untuk mengambil semua penulis, dan satu untuk mengambil semua postingan yang terkait dengan penulis-penulis tersebut. Tanpa eager loading, akan ada satu query untuk mengambil semua penulis, dan kemudian satu query untuk setiap penulis untuk mengambil postingannya.
Anda juga dapat melakukan eager load beberapa relasi:
$authors = Author::with(['posts', 'profile'])->get(); // Eager load "posts" dan "profile"
5. Constraining Eager Loads: Memfilter Relasi yang Dimuat
Anda dapat memfilter relasi yang dimuat menggunakan callback ke method with()
:
$authors = Author::with(['posts' => function ($query) {
$query->where('title', 'like', '%Laravel%');
}])->get();
foreach ($authors as $author) {
echo $author->name . "<br>";
foreach ($author->posts as $post) {
echo "- " . $post->title . "<br>"; // Hanya postingan dengan judul yang mengandung "Laravel"
}
}
Kode ini hanya akan memuat postingan yang judulnya mengandung kata “Laravel”. Ini berguna untuk memfilter data terkait berdasarkan kriteria tertentu.
Relasi One-to-Many Polymorphic
Laravel juga mendukung relasi one-to-many polymorphic. Ini memungkinkan satu model untuk berelasi dengan banyak model lain pada satu relasi. Contohnya adalah sistem komentar di mana komentar dapat dilampirkan ke postingan, video, atau artikel.
Untuk mengimplementasikannya, Anda akan memerlukan kolom commentable_id
dan commentable_type
di tabel comments
. commentable_id
akan berisi ID dari model yang dikomentari, dan commentable_type
akan berisi nama kelas model yang dikomentari (misalnya, AppModelsPost
, AppModelsVideo
, AppModelsArticle
).
Berikut adalah contoh cara mendefinisikan relasi ini di model:
// app/Models/Comment.php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Comment extends Model
{
public function commentable()
{
return $this->morphTo();
}
}
// app/Models/Post.php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Post extends Model
{
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
}
// app/Models/Video.php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Video extends Model
{
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
}
Kita menggunakan method morphTo()
di model Comment
untuk mendefinisikan relasi polymorphic. Dan kita menggunakan method morphMany()
di model Post
dan Video
untuk mendefinisikan relasi one-to-many polymorphic.
Kesimpulan: Memahami dan Memanfaatkan Relasi One-to-Many di Laravel Eloquent
Relasi one-to-many adalah fondasi penting dalam membangun aplikasi Laravel yang kompleks dengan database relasional. Dengan memahami cara mendefinisikan dan menggunakan relasi ini di Laravel Eloquent, Anda dapat dengan mudah mengambil dan memanipulasi data yang terkait, serta meningkatkan performa aplikasi Anda dengan eager loading. Contoh kode dan penjelasan di atas memberikan dasar yang kuat untuk mulai memanfaatkan kekuatan relasi one-to-many dalam proyek Laravel Anda. Jangan ragu untuk bereksperimen dengan berbagai opsi dan konfigurasi untuk menemukan yang paling sesuai dengan kebutuhan aplikasi Anda. Selamat mencoba!
Sumber Terpercaya
Semoga artikel ini bermanfaat!