Laravel uygulamalarında firstOrNew() ve increment() metodlarını kullanırken beklenmeyen bir davranışla karşılaşmanız mümkündür. Bu makalede, bu iki metodun etkileşimlerini bir envanter takip uygulaması üzerinden ele alacağız.
Amacımız, yeni gelen bir sevkiyat ile mevcut ürünün stok sayısını artırmak. Eğer ürün veritabanında yoksa, öncelikle yeni bir kayıt yaratılacak. firstOrNew() metodunu kullanmak bu iki durumu da ele almak için uygun görünüyordu.
Eğer bu iki metodu daha önce birlikte kullanmışsanız, aşağıda yazılanları bilmek faydalı olacaktır.
$incomingShipment = $inventoryItem::firstOrNew(['product_name' => 'Metallic Coffee Mug']);
$incomingShipment->increment('stock_count', 50);
“Metallic Coffee Mug” veritabanında mevcut değildi. Dolayısıyla firstOrNew() yeni, kaydedilmemiş bir model örneği döndürdü — hiçbir id yok, birincil anahtar yok ve $model->exists = false.
Ardından increment() metodunu çağırdım.
Query Log’unda Neler Vardı
Veritabanında başlangıçta üç ürün bulunuyordu:
| product_name | stock_count |
|---|---|
| macbook air M4 | 10 |
| DELL monitor | 5 |
| Varmilo Keyboard | 3 |
increment('stock_count', 50) çağrısının ardından, her bir satır güncellendi:
| product_name | stock_count |
|---|---|
| macbook air M4 | 60 |
| DELL monitor | 55 |
| Varmilo Keyboard | 53 |
Hiçbir hata veya uyarı yoktu. Coffee Mug hâlâ mevcut değil — increment() yeni bir kayıt eklemedi.
increment() Nasıl Çalışır
Kaynağa incelediğimizde, increment() metodunun arka planda incrementOrDecrement() metodunu çağırdığını ve bunun $this->exists kontrolünü yaptığını göreceğiz.
Eğer exists = false ise, model henüz kaydedilmemiş demektir — ve sorguyu WHERE ifadesi olmadan çalıştırır. Böylece tüm tablo etkilenir.
Eğer exists = true ise, sorguyu modelin birincil anahtarına yönelik sınırlar. Bu genellikle beklenen davranıştır.
firstOrNew() hiçbir kayıt bulamazsa kaydedilmemiş bir model döndürür. Dolayısıyla exists değeri false olur ve increment() de sınırlandırılmış sorgu yolunu alır.
Bu İki Metodu Doğru Şekilde Kullanma
exists özelliğini bildiğinizde, bu davranış tam anlamıyla anlaşılır bir hâl alır. Çözüm, increment() çağrısından önce modelin kaydedilmesini sağlamaktır.
$incomingShipment = $inventoryItem::firstOrNew(['product_name' => 'Metallic Coffee Mug']);
if (! $incomingShipment->exists) {
$incomingShipment->stock_count = 0;
$incomingShipment->save();
}
$incomingShipment->increment('stock_count', 50);
Alternatif olarak, firstOrCreate() metodunu kullanarak kayıt doğrudan oluşturulabilir; böylece increment() her zaman bir id ile çalışır.
Eloquent’un iç yapısına daldıkça, exists bayrağı etrafında nasıl tutarlı bir biçimde tasarlandığını görüyorum. Bu küçük özellik, birçok metodun sessizce bağımlı olduğu bir özelliktir.
Kaynak: Orijinal Makale


