Eloquent adalah ORM (Object-Relational Mapping) bawaan Laravel yang membuat interaksi dengan database terasa seperti bekerja dengan objek PHP biasa. Alih-alih menulis query SQL panjang, Anda cukup memanggil method pada model. Menguasai Eloquent adalah pembeda antara developer yang menulis kode berantakan dan developer yang menulis kode Laravel yang bersih, cepat, dan mudah dirawat. Artikel ini membahas Eloquent secara menyeluruh dengan contoh nyata.
1. Model Sebagai Representasi Tabel
Setiap model Eloquent mewakili satu tabel. Berdasarkan konvensi, model Post otomatis dipetakan ke tabel posts (bentuk jamak, huruf kecil). Buat model dengan artisan:
php artisan make:model Post
Model minimal cukup seperti ini. Anda hampir tidak perlu konfigurasi apa pun karena Eloquent mengandalkan konvensi:
class Post extends Model
{
protected $fillable = ['title', 'body', 'user_id', 'published'];
}
Properti $fillable menentukan kolom mana yang boleh diisi secara massal lewat create() atau update(). Ini melindungi Anda dari celah mass assignment.
2. Mengambil Data (Read)
Eloquent menyediakan banyak method untuk mengambil data. Berikut yang paling sering dipakai:
$posts = Post::all(); // semua baris
$post = Post::find(1); // cari berdasarkan primary key
$post = Post::findOrFail(1); // 404 jika tidak ada
$first = Post::where('published', true)->first();
$published = Post::where('published', true)
->orderBy('created_at', 'desc')
->take(10)
->get();
Perbedaan penting: get() mengembalikan koleksi (Collection), sedangkan first() mengembalikan satu model atau null. Gunakan findOrFail() di controller agar Laravel otomatis melempar 404 saat data tidak ditemukan.
3. Membuat, Memperbarui, dan Menghapus
Operasi tulis di Eloquent sangat ringkas:
// Create
$post = Post::create([
'title' => 'Belajar Eloquent',
'body' => 'Isi artikel...',
'user_id' => 1,
]);
// Update
$post->update(['title' => 'Judul Baru']);
// Delete
$post->delete();
Ada juga updateOrCreate() yang berguna untuk mencegah duplikat: Eloquent mencari baris yang cocok, memperbaruinya jika ada, atau membuat baris baru jika belum ada.
Post::updateOrCreate(
['slug' => 'belajar-eloquent'], // syarat pencarian
['title' => 'Belajar Eloquent', 'body' => '...']
);
4. Relasi Antar Tabel
Kekuatan sesungguhnya Eloquent ada pada relasi. Bayangkan seorang User memiliki banyak Post, dan setiap Post memiliki banyak Comment.
hasMany dan belongsTo
class User extends Model
{
public function posts()
{
return $this->hasMany(Post::class);
}
}
class Post extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
}
Sekarang Anda bisa mengakses relasi seperti properti biasa:
$user = User::find(1);
foreach ($user->posts as $post) {
echo $post->title;
}
$post = Post::find(1);
echo $post->user->name; // menuju ke pemilik post
belongsToMany (Many-to-Many)
Relasi banyak-ke-banyak, misalnya Post memiliki banyak Tag dan sebaliknya, membutuhkan tabel pivot (biasanya post_tag):
class Post extends Model
{
public function tags()
{
return $this->belongsToMany(Tag::class);
}
}
// Menautkan tag ke post tanpa menghapus yang lama:
$post->tags()->attach([1, 2, 3]);
// Sinkronkan (hapus yang tidak ada di daftar):
$post->tags()->sync([2, 3]);
5. Masalah N+1 dan Eager Loading
Ini konsep yang WAJIB dipahami. Perhatikan kode berikut:
$posts = Post::all();
foreach ($posts as $post) {
echo $post->user->name; // 1 query TAMBAHAN per post!
}
Jika ada 100 post, Laravel menjalankan 1 query untuk mengambil post + 100 query untuk mengambil user masing-masing = 101 query. Inilah masalah N+1. Solusinya adalah eager loading dengan with():
$posts = Post::with('user')->get();
foreach ($posts as $post) {
echo $post->user->name; // tanpa query tambahan
}
Sekarang hanya 2 query total, tidak peduli berapa banyak post. Anda bahkan bisa eager load relasi bersarang: Post::with('user', 'comments.user')->get().
6. Accessor dan Mutator
Accessor mengubah nilai saat data DIBACA, mutator mengubah nilai saat data DISIMPAN. Di Laravel modern, keduanya ditulis dalam satu method menggunakan Attribute:
use Illuminate\Database\Eloquent\Casts\Attribute;
protected function title(): Attribute
{
return Attribute::make(
get: fn ($value) => ucfirst($value),
set: fn ($value) => strtolower($value),
);
}
Dengan ini, judul selalu disimpan dalam huruf kecil, tetapi ditampilkan dengan huruf awal kapital secara otomatis.
7. Query Scope untuk Kode yang Bersih
Scope menyimpan potongan query yang sering dipakai agar controller tetap ringkas. Definisikan dengan prefiks scope:
public function scopePublished($query)
{
return $query->where('published', true);
}
Pemanggilannya tanpa prefiks scope dan bisa dirangkai:
$posts = Post::published()->latest()->get();
Praktik Terbaik Saat Memakai Eloquent
Beberapa kebiasaan berikut akan membuat kode Eloquent Anda tetap sehat dalam jangka panjang:
- Selalu daftarkan
$fillable: jangan andalkan$guarded = []di aplikasi nyata karena membuka celah mass assignment. - Manfaatkan casting: ubah kolom menjadi tipe yang tepat lewat properti
$casts, misalnya'published' => 'boolean'atau'meta' => 'array', agar nilai otomatis dikonversi. - Pilih relasi yang tepat: salah memilih antara
hasOnedanhasManyakan membuat data yang Anda ambil tidak sesuai harapan. - Gunakan
findOrFaildi controller: ini menjaga aplikasi tetap memberi respons 404 yang benar alih-alih error null.
Contoh casting yang sangat sering dipakai:
protected $casts = [
'published' => 'boolean',
'published_at' => 'datetime',
'meta' => 'array',
];
Dengan casting di atas, kolom meta yang tersimpan sebagai JSON otomatis menjadi array PHP saat dibaca, dan kembali menjadi JSON saat disimpan — tanpa perlu json_encode manual.
Kesimpulan
Eloquent membuat Anda berpikir dalam objek dan relasi, bukan SQL mentah. Kunci menguasainya: pahami konvensi model, gunakan relasi untuk menghubungkan data, dan selalu waspada terhadap N+1 dengan eager loading. Dengan accessor, mutator, casting, dan scope, kode Anda akan tetap rapi dan mudah dibaca bahkan saat aplikasi tumbuh besar. Mulailah dari satu model sederhana, lalu tambahkan relasi dan scope secara bertahap seiring kebutuhan fitur bertambah.