Laravel Eloquent Oluşturma ve Güncelleme


165

Yeni bir kayıt eklemek veya varsa güncellemek için kısayol nedir?

<?php

$shopOwner = ShopMeta::where('shopId', '=', $theID)
    ->where('metadataKey', '=', 2001)->first();

if ($shopOwner == null) {
    // Insert new record into database
} else {
    // Update the existing record
}

Sanırım shopIdbirincil anahtarınız değil, değil mi?
Sergiu Paraschiv

@SergiuParaschiv, evet. değil
1myb

@ErikTheDeveloper yanıtını kontrol edin. İşi yapması gereken güzel bir gömülü güzel yöntem gösterir.
cw24

Aynı şey aşağıdaki bağlantıda tamamen yanıtlanmıştır stackoverflow.com/questions/18839941/…
Bashirpour

Yanıtlar:


232

İşte "lu cip" in neden bahsettiğinin tam bir örneği:

$user = User::firstOrNew(array('name' => Input::get('name')));
$user->foo = Input::get('foo');
$user->save();

Laravel'in en son sürümünde bulunan dokümanların güncellenmiş bağlantısı aşağıdadır

Dokümanlar burada: Güncellenmiş bağlantı


1
kesinlikle! 'firstOrNew' ayrıca 4.0 sürümünde (dokümanlarda belirtilmemiştir) bulunur
younes0

2
Ayrıca ($ user-> varsa) kullanarak $ user'ın yeni / alınan olduğunu kontrol edebiliriz.
Ryu_hayabusa

1
@Ryu_hayabusa Muhtemelen yarış koşullarına neden olur
Chris Harrison

yeni sözdizimi 5.5 sürümünde updateOrInsert (dizi $ öznitelikleri, dizi $ değerleri = []) gibi görünüyor: github.com/laravel/framework/blob/5.5/src/Illuminate/Database/…
user1204214 23:18

86

Güncellendi: Ağu 27 2014 - [ updateOrCreateÇekirdek içine inşa ...]

İnsanların hala buna rastlaması durumunda ... Bunu yazdıktan birkaç hafta sonra, bunun aslında Laravel'in Eloquent'in çekirdeğinin bir parçası olduğunu öğrendim ...

Eloquent'ın eşdeğer yöntem (ler) ini araştırmak. Burada görebilirsiniz:

https://github.com/laravel/framework/blob/4.2/src/Illuminate/Database/Eloquent/Model.php#L553

açık: 570 ve: 553

    /**
     * Create or update a record matching the attributes, and fill it with values.
     *
     * @param  array  $attributes
     * @param  array  $values
     * @return static
     */
    public static function updateOrCreate(array $attributes, array $values = array())
    {
        $instance = static::firstOrNew($attributes);

        $instance->fill($values)->save();

        return $instance;
    }

Eski cevap aşağıda


Böyle bir şekilde yapmak için herhangi bir yerleşik L4 işlevselliği olup olmadığını merak ediyorum:

$row = DB::table('table')->where('id', '=', $id)->first();
// Fancy field => data assignments here
$row->save();

Bu yöntemi birkaç hafta önce yarattım ...

// Within a Model extends Eloquent
public static function createOrUpdate($formatted_array) {
    $row = Model::find($formatted_array['id']);
    if ($row === null) {
        Model::create($formatted_array);
        Session::flash('footer_message', "CREATED");
    } else {
        $row->update($formatted_array);
        Session::flash('footer_message', "EXISITING");
    }
    $affected_row = Model::find($formatted_array['id']);
    return $affected_row;
}

Umarım bu yardımcı olur. Herkesin paylaşacak bir tane varsa buna bir alternatif görmek isterim. @erikthedev_


Orada ve ilk olarak adlandırılırYeni / ilklerOrCreate
malhal

@malcolmhall Yukarıdaki yanıtı güncelledim. Eloquent, kendimi yeniden inşa ederken bulduğum birçok özelliğe sahip;) Dokümanlara göz atarken biraz zaman harcamak her zaman iyidir :)
Erik Aybar

paketçinin 4.2.0 sürümü (kararlı 2014/6/1) updateOrCreate içermiyor. Ama kişi kaynağa bakarak uygulayabilir. ModelName::firstOrNew(['param' => 'condition'])->fill(Input::get())->save();yapmalı.
bibstha

3
Laravel'in işlem olarak çalışmadığına dikkat edin, bu yüzden benzersiz anahtarlarınız varsa ve başka bir kullanıcı aynı anahtarla aynı anda oluşturduğunda bir istisna alabilirsiniz. RedBeanPHP'nin avantajlarından birinin bu tür bir şeyin sizin için bir işlemde yapılması olduğuna inanıyorum.
malhal

Fill () kullanımını işaret ettiğiniz için teşekkürler. Bu bana çok yardımcı oldu!
Kıbrıs'ta Rahatlamak

70

2020 Güncellemesi

Olduğu gibi laravel> = 5.3 , birisi kolay bir şekilde bunu nasıl hala merak eğer. Onun kullanarak mümkün: updateOrCreate().

Örneğin, sorulan soru için aşağıdaki gibi bir şey kullanabilirsiniz:

$matchThese = ['shopId'=>$theID,'metadataKey'=>2001];
ShopMeta::updateOrCreate($matchThese,['shopOwner'=>'New One']);

Yukarıdaki kod, ShopMeta tarafından temsil edilen shop_metasve modelin kendisinde aksi belirtilmedikçe büyük olasılıkla ortaya çıkan tabloyu kontrol edecektir.

ve ile giriş bulmaya çalışacaktır.

kolon shopId = $theID

ve

kolon metadateKey = 2001

ve bulursa shopOwnerbulunan satırın sütununu günceller New One.

Birden fazla eşleşen satır bulursa, ilk satırı en düşük birincil olanı güncelleyecektir id.

Hiç bulunmazsa, aşağıdakileri içeren yeni bir satır ekler:

shopId = $theID, metadateKey = 2001veshopOwner = New One

Uyarı Modelinizi kontrol edin $fillableve eklemek veya güncellemek istediğiniz her sütun adının tanımlanmış olduğundan emin olun ve sütunları varsayılan değere veya idsütun otomatik olarak artırılmış bir değere sahip olun .

Aksi takdirde yukarıdaki örnek yürütülürken hata verir:

Illuminate\Database\QueryException with message 'SQLSTATE[HY000]: General error: 1364 Field '...' doesn't have a default value (SQL: insert into `...` (`...`,.., `updated_at`, `created_at`) values (...,.., xxxx-xx-xx xx:xx:xx, xxxx-xx-xx xx:xx:xx))'

Yeni satır eklenirken değere ihtiyaç duyacağımız ve tanımlanmadığı $fillableveya varsayılan değere sahip olmadığı için bir alan olacağı için .

Daha fazla referans için lütfen şu adresteki Laravel Belgelerine bakın: https://laravel.com/docs/5.3/eloquent

Oradan bir örnek:

// If there's a flight from Oakland to San Diego, set the price to $99.
// If no matching model exists, create one.
$flight = App\Flight::updateOrCreate(
    ['departure' => 'Oakland', 'destination' => 'San Diego'],
    ['price' => 99]
);

ki bu hemen hemen her şeyi temizler.

Sorgu Oluşturucu Güncellemesi

Birisi Laravel'de Query Builder'ı kullanmanın mümkün olup olmadığını sordu. İşte laravel dokümanlardan Query Builder için referanstır.

Sorgu Oluşturucu Eloquent ile tamamen aynı şekilde çalışır, bu nedenle Eloquent için geçerli olan her şey Sorgu Oluşturucu için de geçerlidir. Bu özel durumda, sorgu oluşturucunuzla aynı işlevi aşağıdaki gibi kullanın:

$matchThese = array('shopId'=>$theID,'metadataKey'=>2001);
DB::table('shop_metas')::updateOrCreate($matchThese,['shopOwner'=>'New One']);

Tabii ki, DB cephesi eklemeyi unutmayın:

use Illuminate\Support\Facades\DB;

VEYA

use DB;

Umut ediyorum bu yardım eder


Sorgu oluşturucuya ne dersiniz?
Gökyüzü

Ne olmuş? :)
Öğrenci

Aynı şeyi Query Builder ile yapmak istiyorum. Eloquent değil. Mümkün mü?
Gökyüzü

Cevabımı güncelledim, yukarıdaki cevapta "Sorgu Oluşturucu Güncellemesi" bölümünü bulun.
Öğrenci

DB :: table ('shop_metas') :: updateOrCreate yöntemini denedim ama bu Macroable.php satır 59 BadMethodCallException hata veriyor: Yöntem updateOrInsert yok. DB kullanmama rağmen;
Swapnil Shende

17

Kaydetme işlevi:

$shopOwner->save()

zaten ne istersen yap ...

Laravel kodu:

    // If the model already exists in the database we can just update our record
    // that is already in this database using the current IDs in this "where"
    // clause to only update this model. Otherwise, we'll just insert them.
    if ($this->exists)
    {
        $saved = $this->performUpdate($query);
    }

    // If the model is brand new, we'll insert it into our database and set the
    // ID attribute on the model to the value of the newly inserted row's ID
    // which is typically an auto-increment value managed by the database.
    else
    {
        $saved = $this->performInsert($query);
    }

6
Bu bir atomik upert operasyonuna benzemiyor. Değilse, bu yarış koşullarına neden olabilir.
Emil Vikström

Bu kod, modelin DB'den yüklendiğini veya Bellek Tabanlı Model olup olmadığını kontrol etmektir. Güncelleme veya Oluşturma, kontrol edilmesi için anahtar sütunların açık tanımına ihtiyaç duyar ve dolaylı olarak gerçekleştirilemez.
AMIB

17

firstOrNewyoksa kayıt oluşturur ve zaten varsa bir satırı günceller. Ayrıca kullanabilirsiniz updateOrCreateburada tam örnektir

$flight = App\Flight::updateOrCreate(
    ['departure' => 'Oakland', 'destination' => 'San Diego'],
    ['price' => 99]
); 

Oakland'dan San Diego'ya uçuş varsa, fiyatı 99 $ 'a ayarlayın. yoksa yeni satır oluştur

Buradaki Referans Dokümanı: ( https://laravel.com/docs/5.5/eloquent )


7

DBLaravel'de aynı işlevselliğe ihtiyacınız varsa , >= 5.5şunları kullanabilirsiniz:

DB::table('table_name')->updateOrInsert($attributes, $values);

veya steno sürümü $attributesve $valuesaynıdır:

DB::table('table_name')->updateOrInsert($values);

6
$shopOwner = ShopMeta::firstOrNew(array('shopId' => $theID,'metadataKey' => 2001));

Ardından değişikliklerinizi yapın ve kaydedin. FirstOrNew, bulunmazsa eki yapmaz, buna ihtiyacınız varsa firstOrCreate öğesini not edin.


2

Kimliğiniz otomatik artış değilse ve hangisini ekleyeceğinizi / güncelleyeceğinizi biliyorsanız bir seçenek daha:

$object = MyModel::findOrNew($id);
//assign attributes to update...
$object->save();

2

FirstOrCreate yöntemi gibi, updateOrCreate da modele devam eder, bu nedenle save () işlevini çağırmanıza gerek yoktur

// If there's a flight from Oakland to San Diego, set the price to $99.
// If no matching model exists, create one.

$flight = App\Flight::updateOrCreate(
   ['departure' => 'Oakland', 'destination' => 'San Diego'],
   ['price' => 99]
);

Ve sorununuz için

$shopOwner = ShopMeta::updateOrCreate(
   ['shopId' => $theID, 'metadataKey' => '2001'],
   ['other field' => 'val' ,'other field' => 'val', ....]
);

1

Aslında firstOrCreate , kaydın DB'de zaten mevcut olması durumunda güncellenmez . Aslında sadece "id" sütunu için benzersiz değerlere sahip bir tabloyu güncellemem gerektiğinden biraz Erik çözümünü geliştirdim

/**
 * If the register exists in the table, it updates it. 
 * Otherwise it creates it
 * @param array $data Data to Insert/Update
 * @param array $keys Keys to check for in the table
 * @return Object
 */
static function createOrUpdate($data, $keys) {
    $record = self::where($keys)->first();
    if (is_null($record)) {
        return self::create($data);
    } else {
        return self::where($keys)->update($data);
    }
}

Sonra şöyle kullanırsınız:

Model::createOrUpdate(
        array(
    'id_a' => 1,
    'foo' => 'bar'
        ), array(
    'id_a' => 1
        )
);

bunu yapmamakta iyi olan şey: 1. anahtara göre silin ve 2. yeni değerlerle oluşturun. Bunlar hala 2 ameliyattı. oluşturma ve silme durumunda endeksleme zamanından tasarruf etmek?
Hafiz

1

@JuanchoRamone yukarıda yayınlanan gibi (teşekkür @Juancho) benim için çok yararlı, ancak verileriniz dizi ise, böyle biraz değiştirmelisiniz:

public static function createOrUpdate($data, $keys) {
    $record = self::where($keys)->first();
    if (is_null($record)) {
        return self::create($data);
    } else {
        return $record->update($data);
    }
}

Bunun, createOrUpdate yerine güncellenmesi ya da oluşturulması gerektiğine dair kısa bir not
John Shipp

Tamam ama 1000 satır varsa, 1000 sorgu çalışıyor olacak?
Marcelo Agimóvel


-2

bir kullanıcının var olup olmadığını kontrol edin. Eklenmezse

$exist = DB::table('User')->where(['username'=>$username,'password'=>$password])->get();
if(count($exist)  >0) {
    echo "User already exist";;
}
else  {
    $data=array('username'=>$username,'password'=>$password);
    DB::table('User')->insert($data);
}
Laravel 5.4           

SO'ya hoş geldiniz.Kaliteli cevap sağlamak için bu nasıl yanıtlanacağına bir göz atın . ---
thewaywew

Lütfen kullandığınız çerçeveyi, php sürümünü, veritabanını da etiketleyin.
Jason Joslin

1
Laravel 5.4, php7 ve mysql kullanıyorum
Sabrina Abid

Sabrina laravel'de zaten bir fonksiyon mevcut olduğundan ideal bir çözüm değildir. Ama
seninki

Eski okul yöntemi laravel zaten bunun için bir işleve sahiptir. Seçilen cevabı göster
Saeed Ansari
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.