Eloquent Update dan Delete
Update satu/banyak record dan hapus dengan aman.
Update Punya Dua Level yang Berbeda
Ada update lewat instance model (satu baris, lengkap dengan semua fitur model) dan update massal lewat query builder (cepat, tapi mentah). Keduanya terlihat mirip, tapi perilakunya jauh berbeda. Memahami bedanya mencegah bug yang diam-diam merusak data tanpa error.
Update Satu Model
// app/Http/Controllers/PostController.php
$post = Post::find(1);
$post->title = 'Judul Revisi';
$post->save(); // UPDATE hanya untuk kolom yang berubahEloquent melacak atribut mana yang berubah (dirty checking), jadi query UPDATE hanya menyentuh kolom yang benar-benar berubah. Alternatif gaya massal untuk satu model:
// app/Http/Controllers/PostController.php
$post->update(['title' => 'Judul Revisi']); // butuh $fillableupdate() pada instance model memicu event saving/saved dan menghormati $fillable, sama seperti save(). Bedanya hanya gaya penulisan.
Update Massal: Cepat tapi Mentah
// app/Console/Commands/ArsipkanPostLama.php
$affected = Post::where('created_at', '<', now()->subYear())
->update(['status' => 'arsip']);Satu query UPDATE untuk ribuan baris tanpa memuat model ke memori. update() mengembalikan jumlah baris yang terpengaruh (integer), berguna untuk laporan command ("1.240 post diarsipkan").
Jebakan terbesar: update massal TIDAK memicu model events dan TIDAK menjalankan accessor/mutator. Kalau kamu punya event yang mengirim notifikasi saat status berubah, event itu dilewati. Kolom updated_at tetap di-update otomatis oleh query builder, tapi logika di method boot() model tidak jalan. Aturan praktisnya: data penting dan jumlahnya sedikit, ambil modelnya dulu lalu update; data massal dan sederhana, pakai update massal.
Delete: Tiga Varian
// app/Http/Controllers/PostController.php
$post = Post::find(1);
$post->delete(); // memicu event deleting/deleted
Post::destroy([1, 2, 3]); // hapus banyak by id, tetap lewat model
Post::where('spam', true)->delete(); // massal, langsung DELETE, tanpa eventdestroy() menerima satu id atau array id, memuat tiap model lalu menghapus satu per satu sehingga event tetap berjalan. Versi where()->delete() mengeksekusi DELETE langsung tanpa memuat model: cepat, tapi tanpa event dan tanpa pengecekan relasi di level aplikasi.
Jebakan umum: memakai where()->delete() padahal ada relasi child yang harus ikut terhapus (komentar milik post). Tanpa cascade di database dan tanpa event model, komentar jadi yatim piatu. Pilihannya: pakai destroy() agar event jalan, definisikan cascade di relasi, atau set cascadeOnDelete() di foreign key migration.
Catatan teknis: Delete massal tetap menghormati SoftDeletes karena secara internal ia melakukan update deleted_at lewat query builder. Yang hilang hanya model events. Untuk relasi, pola amannya adalah mendefinisikan static::deleting() di method boot() model parent untuk menghapus child, atau mengandalkan foreign key cascadeOnDelete() di database. Kalau butuh hapus permanen vs sementara, lihat modul soft-delete.
touch() dan Update Bersyarat
Kadang kamu hanya ingin memperbarui updated_at tanpa mengubah data lain, misalnya agar post naik ke atas daftar "baru diupdate" saat ada komentar masuk:
// app/Http/Controllers/CommentController.php
$post->touch(); // UPDATE posts SET updated_at = now()Kalau relasi belongsTo didefinisikan dengan ->touch(), memanggil touch() pada child ikut memperbarui updated_at parent-nya. Berguna untuk cache invalidation berbasis timestamp.
Untuk update massal yang aman dari race condition, tambahkan where sebagai pengaman:
// app/Http/Controllers/PostController.php
$updated = Post::where('id', $id)
->where('status', 'draft') // hanya ubah kalau masih draft
->update(['status' => 'published']);Kalau proses lain sudah mengubah statusnya lebih dulu, $updated bernilai 0 dan kamu tahu operasimu tidak melakukan apa-apa. Ini optimistic guard sederhana tanpa perlu lock database.
Tantangan
Arsipkan Post Lama
Via tinker: update semua post yang dibuat lebih dari 1 tahun lalu, set status = 'arsip'. Hitung berapa yang terpengaruh. Lalu hapus 1 post by id dan verifikasi.