Laravel Eloquent, yalnızca değişiklik yapıldıysa güncellenir


87

Laravel'de, sadece o kayıtta bir değişiklik yapıldıysa, anlamlı modeller kullanarak bir kaydı güncellemenin herhangi bir yolu var mı? Hiçbir kullanıcının iyi bir sebep olmadan veritabanını talep etmesini istemiyorum, sadece değişiklikleri kaydetmek için düğmeye basmak. javascriptSayfada bir şeyin değişip değişmediğine göre kaydet düğmesini etkinleştirip devre dışı bırakan bir fonksiyonum var, ancak bu tür bir özelliği sunucu tarafında da yapmanın mümkün olup olmadığını bilmek istiyorum. Bunu kendi başıma başarabileceğimi biliyorum (yani: çerçevenin iç işlevselliğine başvurmadan), sadece kaydın değişip değişmediğini kontrol ederek, ancak bunu bu şekilde yapmadan önce, Laravel belgesel modelinin halihazırda ilgilenip ilgilenmediğini bilmek istiyorum. yani tekerleği yeniden icat etmeme gerek yok.

Bir kaydı güncellemek için kullandığım yol:

$product = Product::find($data["id"]);
$product->title = $data["title"];
$product->description = $data["description"];
$product->price = $data["price"];
//etc (string values were previously sanitized for xss attacks)
$product->save();

3
Neden veritabanı günlüğünü etkinleştirmiyorsunuz ve sonra Eloquent'in bir kaydetme yaptığınızda gerçekte hangi sorguyu çalıştırdığını görmek için günlükleri kontrol etmiyorsunuz: hoş bir şekilde şaşırabilirsiniz
Mark Baker

4
Laravel modellerinin dirty, veritabanında bir güncellemenin gerçekten gerekli olup olmadığını belirlemek için kullanılan bir bayrağı tuttuğunu ve bu bayrağın, orijinal findsütun değerlerini kaydetmeyi gerçekleştirdiğiniz noktadaki değerlerle karşılaştırarak ayarlandığını unutmayın
Mark Baker

@MarkBaker Bu harika bir ipucu!
user2755140

Yanıtlar:


180

Zaten yapıyorsun!

save()modeldeki bir şeyin değişip değişmediğini kontrol edecektir. Değilse, bir db sorgusu çalıştırmaz.

İşte kodun ilgili kısmı Illuminate\Database\Eloquent\Model@performUpdate:

protected function performUpdate(Builder $query, array $options = [])
{
    $dirty = $this->getDirty();

    if (count($dirty) > 0)
    {
        // runs update query
    }

    return true;
}

getDirty()Yöntem basitçe kaydedilmiş bir kopyası ile şimdiki özelliklerini karşılaştırır originalmodeli oluşturulduğunda. Bu syncOriginal()yöntemde yapılır :

public function __construct(array $attributes = array())
{
    $this->bootIfNotBooted();

    $this->syncOriginal();

    $this->fill($attributes);
}

public function syncOriginal()
{
    $this->original = $this->attributes;

    return $this;
}

Modelin kirli olup olmadığını kontrol etmek isterseniz arayın isDirty():

if($product->isDirty()){
    // changes have been made
}

Veya belirli bir özelliği kontrol etmek istiyorsanız:

if($product->isDirty('price')){
    // price has changed
}

Bu harika. Teşekkür ederim. Şimdi merak ediyorum, herhangi bir değişiklik yapmadan güncelleme girişiminde bulunulduğunu bilmek için bu kirli bayrağa nasıl erişebilirim? Demek istediğim: bu eylemin geri dönüşü?
user2755140

1
@DaseinA Bunun için kullanabilirsiniz isDirty(). Güncellenen yanıtı görün
lukasgeiter

2
Bunu okuyanlar için, kullanmadan önce bu cevabı kontrol ettiğinizden emin olun isDirty().
Alex

1
Orada getChanges()yöntemi. Cevabımı kontrol edin stackoverflow.com/a/54132163/1090395
Mladen Janjetovic

Bilginize isDirty(), trueniteliklerinizi doğru bir şekilde atmazsanız olacağım Veritabanındaki ile tamamen aynı olan bir float'ım vardı, ancak float'ı bir dizeyle ayarladığım için (örneğin 10.50 yerine "10.50") bunu bir değişiklik olarak algılar ve bir güncelleme gerçekleştirirdi.
Maarten de Graaf


11

Bu yöntemi eklemeyi seviyorum, bir düzenleme formu kullanıyorsanız, bu kodu update(Request $request, $id)işlevinizdeki değişiklikleri kaydetmek için kullanabilirsiniz :

$post = Post::find($id);    
$post->fill($request->input())->save();

girişlerinizi aynı sütun adıyla adlandırmanız gerektiğini unutmayın. fill()Fonksiyon sizin için tüm çalışmaları yapacağız :)


3
Aslında aradığım cevap bu, adı fillve ona nasıl toplu geçiş yapacağımı unuttum . Teşekkürler! Güncelleme yaptığımdan beri kimliği geçmeme gerek yoktu, bu yüzden zaten orada $request->id.
2017'yi
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.