2013-02-27 163 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. */ 
}