2013-02-27 18 views
54

EOxperent ORM jest całkiem niezły, chociaż zastanawiam się, czy istnieje prosty sposób na skonfigurowanie transakcji MySQL za pomocą innoDB w taki sam sposób, jak PDO, lub gdybym musiał rozszerzyć ORM, aby to zrobić możliwy?Laravel Eloquent ORM Transakcje

Odpowiedz

110

Można to zrobić:

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

Wszystko wewnątrz Zamknięcie wykonuje w ramach transakcji. Jeśli wystąpi wyjątek, zostanie on automatycznie wycofany.

+1

Wewnątrz zamknięcia mogę zadzwonić zapytań w klasie? To zadziała? –

+0

Niestety nie działa to dla mnie, jeśli tworzę wystąpienie różnych modeli, które przechowują rekord w swoich własnych odpowiednich metod. – Volatil3

+0

Jeśli przechwyciłem wyjątek w ramach transakcji (generowania komunikatów o błędach itd.), Czy muszę ponownie emitować wyjątek, aby nastąpiło wycofanie? – alexw

64

Jeśli nie podoba anonimowe funkcje:

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

Aktualizuj: Dla laravel 4 przedmiot pdo nie jest już tak publiczny:

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

Można również użyć metod skrótów 'DB :: beginTransaction()' & 'DB :: commit()' & 'DB :: rollback()'. To byłoby trochę czystsze. – Flori

+2

Zaktualizuj, aby użyć sugestii @Flori. Jest czystszy. Przeniesienie nowej odpowiedzi w górę spowoduje, że twoja odpowiedź będzie mniej kłopotliwa. Użyłem pierwszej metody, zanim wróciłem na drugą. – frostymarvelous

18

Jeśli chcesz użyć Eloquent, możesz również użyć tego

Jest to kod tylko próbka z mojego projektu

 /* 
     * 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(); 
     }); 
+0

próbowałem coś podobnego, ale nie działa wstawić transakcję i kwota transakcji jest dziesiętny (5, 2) i wstawić wartość 999999.99999, potem biegnę drugą wymowny który odliczenia/zwiększenie kredytu użytkownika (ważne), spodziewam powinny rzucać błąd i wycofanie z powodu wartości dziesiętnej transakcji jest w złym formacie, ale transakcja po prostu wstawiona z pustą wartością i kredyt użytkownika również odejmuje nieoczekiwane, czy wiesz dlaczego? – user259752

6

Z jakiegoś powodu jest to dość trudne do znalezienia informacji gdziekolwiek, więc zdecydowałem się opublikować go tutaj, ponieważ mój problem, a związanych z transakcjami wymowny, został dokładnie zmienia to.

Po przeczytaniu odpowiedzi Stackoverflow THIS, zdałem sobie sprawę, że moje tabele bazy danych używają MyISAM zamiast InnoDB.

dla transakcji do pracy na laravel (lub gdziekolwiek indziej, jak się wydaje), wymagane jest, że stoliki są ustawione na korzystanie InnoDB

Dlaczego?

Cytowanie MySQL transakcji i operacji atomowe docs (here):

MySQL Server (wersja 3.23-max i wszystkie wersje 4,0 i powyżej) obsługuje transakcje z silników przechowywania transakcyjny InnoDB i BDB. InnoDB zapewnia pełną zgodność z ACID. Zobacz Rozdział 14, Silniki pamięci masowej. Aby uzyskać informacje o różnicach InnoDB w stosunku do standardowego SQL w odniesieniu do traktowania błędów transakcji, zobacz Rozdział 14.2.11, "Obsługa błędów InnoDB".

Inne nietransakcyjne silniki pamięci masowej w serwerze MySQL (takie jak MyISAM) mają inny paradygmat integralności danych zwany "operacjami atomowymi". W terminach transakcyjnych tabele MyISAM zawsze działają w trybie autocommit = 1. Operacje atomowe często oferują porównywalną spójność z wyższą wydajnością.

Ponieważ serwer MySQL obsługuje oba paradygmaty, możesz zdecydować, czy Twoje aplikacje są najlepiej obsługiwane przez szybkość operacji atomowych lub korzystanie z funkcji transakcyjnych. Ten wybór może być dokonany na podstawie tabeli.

+0

Dotyczy to DML i nie zawsze jest prawdziwe dla DDL. –

10

Jeśli chcesz uniknąć zamknięcia i chętnie korzystać elewacje, następujące utrzymuje rzeczy ładne i czyste:

\DB::beginTransaction(); 

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

\DB::commit(); 

Jeśli wszelkie oświadczenia nie popełniają nigdy nie trafi, a transakcja nie będzie proces.

6

Jestem pewien, że nie szuka rozwiązania zamknięcia, spróbuj tego bardziej kompaktowe rozwiązanie

try{ 
    DB::beginTransaction(); 

    /* 
    * Your DB code 
    * */ 

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

Jeśli wystąpi wyjątek, transakcja będzie wycofać się automatycznie.

Format transakcja laravel Podstawowe

try{ 
    DB::beginTransaction(); 

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


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

    DB::rollback(); 
    /* Transaction failed. */ 
} 
Powiązane problemy