Laravel Eloquent ORM Сделки

55

Eloquent ORM довольно приятный, хотя мне интересно, есть ли простой способ настроить транзакции MySQL с помощью innoDB так же, как PDO, или если мне придется расширить ORM, чтобы сделать это возможным?

Теги:

7 ответов

103
Лучший ответ

Вы можете сделать это:

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

Все внутри Closure выполняется внутри транзакции. Если произойдет исключение, он автоматически откатится.

  • 1
    Внутри замыкания я могу вызывать запросы в классе? Это будет работать?
  • 0
    К сожалению, это не работает для меня, если я создаю экземпляр различных моделей, которые хранят записи в своих собственных соответствующих методах.
Показать ещё 5 комментариев
61

Если вам не нравятся анонимные функции:

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() . Это было бы немного чище.
  • 2
    Пожалуйста, обновите, чтобы использовать предложение @Flori. Это чище. Кроме того, перемещение нового ответа вверх сделает ваш ответ менее запутанным. Я использовал первый метод, прежде чем вернуться ко второму.
Показать ещё 1 комментарий
16

Если вы хотите использовать 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();
        });
9

Если вы хотите избежать закрытий и счастливы использовать фасады, следующее держит вещи приятными и чистыми:

\DB::beginTransaction();

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

\DB::commit();

Если какие-либо утверждения терпят неудачу, commit никогда не ударит, и транзакция не будет обрабатываться.

6

Я уверен, что вы не ищете решение для закрытия, попробуйте это для более компактного решения

 try{
    DB::beginTransaction();

    /*
     * Your DB code
     * */

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

По какой-то причине довольно сложно найти эту информацию в любом месте, поэтому я решил опубликовать ее здесь, так как моя проблема, связанная с транзакциями Eloquent, точно меняла это.

После чтения ЭТО ответ stackoverflow, я понял, что мои таблицы базы данных использовали MyISAM вместо InnoDB.

Чтобы транзакции работали на Laravel (или где-либо еще, как кажется), требуется, чтобы ваши таблицы были настроены на использование InnoDB

Почему?

Цитата MySQL Транзакции и Атомные операции docs (здесь):

Сервер MySQL (версия 3.23-max и все версии 4.0 и выше) поддерживает транзакции с транзакционными системами хранения данных InnoDB и BDB. InnoDB обеспечивает полное соответствие требованиям ACID. См. Главу 14 "Двигатели хранения". Информацию о различиях InnoDB от стандартного SQL в отношении обработки ошибок транзакций см. В разделе 14.2.11 "Обработка ошибок InnoDB".

Другие нетранзакционные системы хранения в MySQL Server (такие как MyISAM) следуют другой парадигме для целостности данных, называемой "атомарные операции". В транзакционных условиях таблицы MyISAM эффективно работают в режиме autocommit = 1. Атомные операции часто обеспечивают сопоставимую целостность с более высокой производительностью.

Поскольку MySQL Server поддерживает обе парадигмы, вы можете решить, лучше ли ваши приложения обслуживать скорость атомных операций или использование транзакционных функций. Этот выбор можно сделать на основе таблицы.

  • 0
    Это верно для DML и не всегда верно для DDL.
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. */
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню