2013-02-27 85 views
54

Eloquent ORM相當不錯,不過我想知道是否有一種簡單的方法可以像使用PDO一樣使用innoDB來設置MySQL事務,或者如果我將擴展ORM來實現這一點可能?Laravel Eloquent ORM交易

回答

110

你可以這樣做:

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

瓶蓋內的一切事務中執行。如果發生異常,它將自動回滾。

+1

關閉我可以打電話查詢,在類中?它會起作用嗎? – 2015-05-14 16:56:37

+0

可悲的是,如果我正在用自己的相關方法創建存儲記錄的不同模型的實例,則不適用於我。 – Volatil3 2015-08-28 11:22:18

+0

如果我在事務內部捕獲異常(用於生成錯誤消息等),是否需要重新發出異常以進行回滾? – alexw 2016-02-19 19:04:36

64

如果你不喜歡匿名函數:

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

更新:對於laravel 4,pdo對象是不公開了,所以:

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

您也可以使用快捷方法'DB :: beginTransaction()'&'DB :: commit()'&'DB :: rollback()'。這將是一個更清潔。 – Flori 2014-02-03 22:59:39

+2

請更新以使用@Flori建議。它更乾淨。此外,向上移動新答案將使您的答案更加容易混淆。在回來之前我使用了第一種方法。 – frostymarvelous 2014-02-22 22:52:22

18

如果您想用Eloquent,你也可以用這個

這只是示例代碼從我的項目

 /* 
     * 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

我試過類似的東西,但沒有工作 我插入交易和交易金額是十進制(5,2),我插入價值999999.99999,然後我運行第二雄辯扣除/增加用戶信用(有效),我期望應該拋出由於事務小數的錯誤和回滾格式不正確,但剛剛插入空白值和用戶信用的事務也會扣除意外,您知道爲什麼嗎? – user259752 2014-08-21 14:45:09

6

出於某種原因,這是相當困難的地方找到這些信息,所以我決定把它張貼在這裏,因爲我的問題,而涉及到口才交易,正是改變這個。

在讀取THIS stackoverflow答案後,我意識到我的數據庫表使用MyISAM而不是InnoDB。

有關交易對Laravel(或任何其他地方,因爲它似乎)一起工作,它要求你的表被設置爲使用InnoDB

爲什麼?

引用的MySQL 事務和原子操作文檔(here):

MySQL服務器(版本3.23-max和所有版本4.0及以上),支持與InnoDB和BDB事務存儲引擎的事務。 InnoDB提供完整的ACID合規性。請參閱第14章,存儲引擎。有關InnoDB與標準SQL在處理事務錯誤方面的差異的信息,請參見第14.2.11節「InnoDB錯誤處理」。其他非事務性存儲引擎(如MyISAM)遵循不同的數據完整性範例,稱爲「原子操作」。在事務性條款中,MyISAM表總是以autocommit = 1模式運行。原子操作通常提供可比較的完整性和更高的性能。

由於MySQL服務器支持這兩種範例,因此您可以根據原子操作的速度或使用事務功能來決定應用程序的最佳服務。這種選擇可以基於每個表格進行。

+0

這對於DML是正確的,對於DDL並不總是正確的。 – 2015-11-18 02:49:37

10

如果你想避免倒閉,並樂於使用的外牆,下面讓事情非常乾淨:

\DB::beginTransaction(); 

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

\DB::commit(); 

如果任何語句失敗,提交永遠不會打,並且交易不會處理。

6

我敢肯定,你是不是在找一個封閉的解決方案,嘗試這種更緊湊的解決方案

try{ 
    DB::beginTransaction(); 

    /* 
    * Your DB code 
    * */ 

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

如果出現任何異常,交易將自動回滾。

Laravel交易基本格式

try{ 
    DB::beginTransaction(); 

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


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

    DB::rollback(); 
    /* Transaction failed. */ 
}