Laravel
Daha fazla count + 1 yapma !
Merhabalar,
Laravel ile proje geliştirdiğimiz zaman bazen basit işlemler için yanlış methodlar kullanılabiliyor.
Bunlardan bir tanesi ise count+1 işlemi.
Geçenlerde simple bir proje geliştirirken ,olabildiğince hızlı şekilde bitirmem gerektiğinden, (daha sonra refactor edilmek üzere) yüzlerce satır kod yazdım.
Daha sonra refactoring sırasında bu daha kısaydı bu daha doğru diye diye neredeyse baştan yazdım :)
Bunlardan bir tanesi her içerik için görüntülenme sayısının tutulduğu view_count sütunu için arttırma işlemiydi.
Aşağıdaki örnekte daha net anlaşılır olacaktır. İnceledikten sonra neden hangisini kullanmalıyız kısmını inceleyelim.
Kullanımlar :
public function show($slug)
{
$blog = $this->model->where('slug', $slug)->firstOrFail();
$blog->increment('view_count');
return view('frontend.pages.blog_show', compact('blog'));
}
public function showMe($slug)
{
$blog = $this->model->where('slug', $slug)->firstOrFail();
$blog->view_count = $blog->view_count + 1;
$blog->save();
return view('frontend.pages.blog_show', compact('blog'));
}
İki yöntem de kullanılabilir yöntemdir. Hatta pek çok projede doğrudan ikinci yöntem kullanılır. Peki doğrusu bu mudur ? Projeye göre değişir ama doğru yöntem şudur demek için tek delil bu iki fonksiyon olamaz.
Arasındaki farkı anlatmadan önce increment methodunu incelemekte fayda var.
/**
* Increment a column's value by a given amount.
*
* @param string $column
* @param float|int $amount
* @param array $extra
* @return int
*/
protected function increment($column, $amount = 1, array $extra = [])
{
return $this->incrementOrDecrement($column, $amount, $extra, 'increment');
}
/**
* Decrement a column's value by a given amount.
*
* @param string $column
* @param float|int $amount
* @param array $extra
* @return int
*/
protected function decrement($column, $amount = 1, array $extra = [])
{
return $this->incrementOrDecrement($column, $amount, $extra, 'decrement');
}
Kaynağına gittiğimizde şunu anlıyoruz. İlk kod örneğinde iki farklı yöntem göstermiştim. O bloglarda showMe methodu vardı. Onun üzerinden gidelim.
Kullanıcı geldi , 15 görüntülenmesi olan bu bloğu görüntülemek istedi. Bu sırada siz o blog için view_count değerini +1 yaptınız ve kaydettiniz. Değerin 16 oldu sorun yok :)
Şimdi diyelim ki anlık olarak binlerce kullanıcı olan bir sisteme sahip oldunuz. Blog görüntülenmeniz 10.000 diyelim. Şimdi aynı bloğu aynı anda 1000 kişi görürse sonuç ne olur ?
101000 olacağını düşünüyorsanız geçmiş olsun yanıldınız. +1 yöntemini yaptığınz sırada sistem bir başka kullanıcıya yanıt vermiş ve zaten güncellemişti. 10.005 belki 10.010 olmuştu ancak sizin elinizdeki objede halen 10.000 değeri var.
Bu yüzden siz görüntülediğiniz anda 10.010 değer 10.001 olarak güncellendi ve siz 1 arttırmak isterken onun yerine değeri çokca düşürüldü.
İkinci yöntemde bu senaryoda herhangi bir sorun yaşamadan 11.000 olarak görecektiniz.
Peki ama neden ?
Çünkü ilk kod eldeki objeyi güncelliyor. İlk başta objeyi çekti, değerini arttırıp set etti ve sonunda tekrar db connection açıp doğrudan update edilecek değeri verdi.
İkinci yöntemde ise kullanıcı bloğu görmek istediğinde objeyi çektik. Laravelin increment fonksiyonu ile veritabanına şunu dedik , "kardeşim elindeki değer ne ise ona bir ekleyiver sana zahmet".
Bu yüzden iki yöntem arasında veri doğruluğu açısından önemli farklar bulunuyor.
Daha fazla içerik için siteyi favorilere ekleyebilirsin.