Laravel Eloquent ORM Transactions


Laravel Eloquent ORM Transactions

Eloquent ORM非常不错,不过我想知道是否有一种简单的方法可以像PDO一样使用innoDB设置MySQL事务,或者我是否必须扩展ORM才能实现这一点?

您可以这样做:

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

闭包中的所有内容都在事务中执行。如果发生异常,它将自动回滚。

如果你不喜欢匿名函数:

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();
}

如果你想避免闭包,并乐于使用外立面,以下内容可以保持事物的整洁:

try {
    'DB::beginTransaction();
    $user = 'Auth::user();
    $user->fill($request->all());
    $user->push();
    'DB::commit();
} catch (Throwable $e) {
    'DB::rollback();
}

如果任何语句失败,提交将永远不会命中,事务也不会处理。

如果你想使用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();
        });

我相信你不是在寻找一个闭包解决方案,试试这个更紧凑的解决方案

 try{
    DB::beginTransaction();
    /*
     * Your DB code
     * */
    DB::commit();
}catch('Exception $e){
    DB::rollback();
}

由于某种原因,在任何地方都很难找到这些信息,所以我决定将其发布在这里,因为我的问题虽然与Eloquent事务有关,但正是改变了这一点。

在阅读了THIS stackoverflow的答案后,我意识到我的数据库表使用的是MyISAM而不是InnoDB。

对于要在Laravel(或其他任何地方(上工作的事务,需要将表设置为使用InnoDB

为什么?

引用MySQL事务和原子操作文档(此处(:

MySQL Server(3.23-max版本和所有4.0及以上版本(支持使用InnoDB和BDB事务存储引擎的事务。InnoDB提供完全的ACID合规性。请参阅第14章,存储引擎。有关InnoDB与标准SQL在处理事务错误方面的差异的信息,请参阅第14.2.11节"InnoDB错误处理"。

MySQL Server中的其他非事务存储引擎(如MyISAM(遵循一种不同的数据完整性范式,称为"原子操作"。从事务的角度来看,MyISAM表始终有效地以autocommit=1模式运行。原子操作通常提供类似的完整性和更高的性能。

因为MySQL Server支持这两种模式,所以您可以决定是原子操作的速度还是事务功能的使用为您的应用程序提供了最佳服务。这个选择可以在每张表的基础上进行。

如果发生任何异常,事务将自动回滚。

Laravel基本交易格式

    try{
    DB::beginTransaction();
    /* 
    * SQL operation one 
    * SQL operation two
    ..................     
    ..................     
    * SQL operation n */

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

最佳且清晰的方式:

DB::beginTransaction();
try {
    DB::insert(...);
    DB::insert(...);
    DB::insert(...);
    DB::commit();
    // all good
} catch ('Exception $e) {
    DB::rollback();
    // something went wrong
}