Laravel Eloquent ORM İşlemleri


97

Eloquent ORM oldukça güzel, yine de innoDB'yi PDO ile aynı şekilde kullanarak MySQL işlemlerini kurmanın kolay bir yolu olup olmadığını veya bunu mümkün kılmak için ORM'yi genişletmem gerekip gerekmediğini merak ediyorum.

Yanıtlar:


166

Bunu yapabilirsiniz:

DB::transaction(function() {
      //
});

Kapanış içindeki her şey bir işlem içinde yürütülür. Bir istisna oluşursa, otomatik olarak geri alınacaktır.


1
Kapanış içinde bir sınıftaki soruları arayabilir miyim? Çalışacak mı?
Rafael Soufraz

Kayıtları kendi ilgili yöntemlerinde depolayan farklı modellerin örneklerini oluşturuyorsam ne yazık ki benim için işe yaramıyor.
Volatil3

İşlemimde bir istisna yakalarsam (hata mesajları üretmek için vb.), Geri dönüşün gerçekleşmesi için istisnayı yeniden yayınlamam gerekir mi?
alexw

3
İyi yanıt ama birkaç şey beni yakaladı: 1. "DB kullan" eklemeniz gerekiyor; bunu yapmak için, örneğin model dosyanızın üstünde 2. JS'nin aksine, ana etki alanındaki yerel değişkenlere, onları açıkça iletmedikçe erişemezsiniz, bu şekilde "kullan" yapısını eklemeniz gerekir ... DB :: transaction (function () use ($ user) {... $ user ...} ile ilgili maddeler);
Polsonby

Discussed in more detail herebağlantı öldü.
tomloprod

101

Anonim işlevleri sevmiyorsanız:

try {
    DB::connection()->pdo->beginTransaction();
    // database queries here
    DB::connection()->pdo->commit();
} catch (\PDOException $e) {
    // Woopsy
    DB::connection()->pdo->rollBack();
}

Güncelleme : Laravel 4 için pdonesne artık herkese açık değil, bu yüzden:

try {
    DB::beginTransaction();
    // database queries here
    DB::commit();
} catch (\PDOException $e) {
    // Woopsy
    DB::rollBack();
}

15
Ayrıca kısayol yöntemlerini kullanabilirsiniz DB::beginTransaction()& DB::commit()& DB::rollback(). Bu biraz daha temiz olur.
Flori

2
@Flori önerisini kullanmak için lütfen güncelleyin. Daha temiz. Ayrıca, yeni cevabı yukarı taşımak, cevabınızı daha az kafa karıştırıcı hale getirecektir. İkincisi için geri dönmeden önce ilk yöntemi kullandım.
frostymarvelous

Laravel'in eski sürümü için şunlara ihtiyacınız olabilir:DB::connection()->getPdo()->beginTransaction();
bunun yerine

Kişisel DB::transactionolarak geri arama ile geri
aramanın

33

Eloquent'i kullanmak istiyorsanız, bunu da kullanabilirsiniz

Bu sadece projemden örnek kod

        /* 
         * Saving Question
         */
        $question = new Question;
        $questionCategory = new QuestionCategory;

        /*
         * Insert new record for question
         */
        $question->title = $title;
        $question->user_id = Auth::user()->user_id;
        $question->description = $description;
        $question->time_post = date('Y-m-d H:i:s');

        if(Input::has('expiredtime'))
            $question->expired_time = Input::get('expiredtime');

        $questionCategory->category_id = $category;
        $questionCategory->time_added = date('Y-m-d H:i:s');

        DB::transaction(function() use ($question, $questionCategory) {

            $question->save();

            /*
             * insert new record for question category
             */
            $questionCategory->question_id = $question->id;
            $questionCategory->save();
        });

question->idİşlem geri arama, ifade sıfır döndürür.
Christos Papoulas

@ChristosPapoulas, işlemde otomatik artış kimliğini alamayacağımızı mı söylediniz?
hellojinjie

30

Kapanmalardan kaçınmak ve cepheleri kullanmaktan memnunsanız, aşağıdakiler her şeyi güzel ve temiz tutar:

try {
    \DB::beginTransaction();

    $user = \Auth::user();
    $user->fill($request->all());
    $user->push();

    \DB::commit();

} catch (Throwable $e) {
    \DB::rollback();
}

Herhangi bir ifade başarısız olursa, commit asla isabet etmez ve işlem işlenmez.


Herhangi bir ifade başarısız olursa, sonraki ifadeler çalışmaz. Yine de işlemi açıkça geri almanız gerekir.
Jason

1
@Jason Cevabı güncelledim. Çoğu (tümü?) Veritabanı motoru için, bağlantı sonlandırıldığında, yapmamam gerekip gerekmediğine dair iki fikirdeydim, herhangi bir işlem sorgusu işlenmeyecek. Ancak, söylediklerinize katılıyorum ve muhtemelen en iyisi açık olmak gerekirse
Chris

19

Eminim bir kapatma çözümü aramıyorsunuz, daha kompakt bir çözüm için bunu deneyin

 try{
    DB::beginTransaction();

    /*
     * Your DB code
     * */

    DB::commit();
}catch(\Exception $e){
    DB::rollback();
}

10

Bazı nedenlerden dolayı bu bilgiyi herhangi bir yerde bulmak oldukça zor, bu yüzden burada yayınlamaya karar verdim, çünkü benim sorunum Eloquent işlemleriyle ilgili olsa da, tam olarak bunu değiştiriyordu.

BU stackoverflow cevabını okuduktan sonra , veritabanı tablolarımın InnoDB yerine MyISAM kullandığını fark ettim.

İşlemlerin Laravel'de (veya göründüğü gibi başka herhangi bir yerde) çalışması için, tablolarınızın InnoDB'yi kullanacak şekilde ayarlanmış olması gerekir.

Neden?

MySQL İşlemlerinden ve Atomik İşlem belgelerinden alıntı yapma ( burada ):

MySQL Server (sürüm 3.23-max ve tüm sürüm 4.0 ve üzeri) InnoDB ve BDB işlem depolama motorları ile işlemleri destekler. InnoDB, tam ACID uyumluluğu sağlar. Bölüm 14, Depolama Motorları'na bakın. İşlem hatalarının ele alınmasına ilişkin olarak standart SQL'den InnoDB farklılıkları hakkında bilgi için bkz. Bölüm 14.2.11, "InnoDB Hata İşleme".

MySQL Sunucusundaki (MyISAM gibi) diğer işlemsel olmayan depolama motorları, veri bütünlüğü için "atomik işlemler" adı verilen farklı bir paradigmayı izler. İşlem açısından, MyISAM tabloları her zaman etkin bir şekilde autocommit = 1 modunda çalışır. Atomik işlemler genellikle daha yüksek performansla karşılaştırılabilir bütünlük sunar.

MySQL Sunucusu her iki paradigmayı da desteklediğinden, uygulamalarınızın en iyi atomik işlemlerin hızıyla mı yoksa işlem özelliklerinin kullanımıyla mı sunulacağına karar verebilirsiniz. Bu seçim, tablo bazında yapılabilir.


Bu, DML için doğrudur ve DDL için her zaman doğru değildir.
Yevgeniy Afanasyev

4

Herhangi bir istisna olursa, işlem otomatik olarak geri alınacaktır.

Laravel Basic işlem biçimi

    try{
    DB::beginTransaction();

    /* 
    * SQL operation one 
    * SQL operation two
    ..................     
    ..................     
    * SQL operation n */


    DB::commit();
   /* Transaction successful. */
}catch(\Exception $e){       

    DB::rollback();
    /* Transaction failed. */
}
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.