Eloquent ORM довольно хорош, хотя мне интересно, есть ли простой способ настроить транзакции MySQL с использованием innoDB таким же образом, как и PDO, или мне придется расширить ORM, чтобы это стало возможным?
Ответы:
Ты можешь сделать это:
DB::transaction(function() {
//
});
Все внутри Closure выполняется внутри транзакции. В случае возникновения исключения произойдет автоматический откат.
Discussed in more detail hereссылка мертва.
Если вам не нравятся анонимные функции:
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();
}
DB::beginTransaction()& DB::commit()& DB::rollback(). Это было бы немного чище.
DB::connection()->getPdo()->beginTransaction();
DB::transactionобратный вызов with еще чище, но недостатком является то, что если вам нужно указать разные обработчики для разных исключений, вам придется вернуться, чтобы попробовать / поймать технику
Если вы хотите использовать 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();
});
question->idВыражение на обратный вызов транзакции возвращает ноль.
Если вы хотите избежать закрытия и использовать фасады, следуйте инструкциям, чтобы сохранить чистоту и порядок:
try {
\DB::beginTransaction();
$user = \Auth::user();
$user->fill($request->all());
$user->push();
\DB::commit();
} catch (Throwable $e) {
\DB::rollback();
}
Если какой-либо оператор завершится ошибкой, фиксация никогда не будет выполнена, и транзакция не будет обработана.
Я уверен, что вы не ищете решение для закрытия, попробуйте это для более компактного решения
try{
DB::beginTransaction();
/*
* Your DB code
* */
DB::commit();
}catch(\Exception $e){
DB::rollback();
}
По какой-то причине довольно сложно где-либо найти эту информацию, поэтому я решил опубликовать ее здесь, поскольку моя проблема, хотя и была связана с транзакциями Eloquent, как раз меняла это.
После прочтения ЭТОГО ответа stackoverflow я понял, что в моих таблицах базы данных используется MyISAM вместо InnoDB.
Чтобы транзакции работали на Laravel (или где-то еще, как кажется), необходимо, чтобы ваши таблицы были настроены на использование InnoDB.
Зачем?
Цитата из документов MySQL Transactions и Atomic Operations ( здесь ):
Сервер MySQL (версия 3.23-max и все версии 4.0 и выше) поддерживает транзакции с механизмами хранения транзакций InnoDB и BDB. InnoDB обеспечивает полное соответствие ACID. См. Главу 14, Механизмы хранения. Для получения информации об отличиях InnoDB от стандартного SQL в отношении обработки ошибок транзакций см. Раздел 14.2.11, «Обработка ошибок InnoDB».
Другие механизмы нетранзакционного хранения в MySQL Server (такие как MyISAM) следуют другой парадигме целостности данных, называемой «атомарными операциями». С точки зрения транзакций таблицы MyISAM всегда работают в режиме autocommit = 1. Атомарные операции часто предлагают сопоставимую целостность с более высокой производительностью.
Поскольку сервер MySQL поддерживает обе парадигмы, вы можете решить, лучше ли обслуживаются ваши приложения за счет скорости атомарных операций или использования транзакционных функций. Этот выбор может быть сделан для каждой таблицы.
Если произойдет какое-либо исключение, транзакция откатится автоматически.
Формат транзакции Laravel Basic
try{
DB::beginTransaction();
/*
* SQL operation one
* SQL operation two
..................
..................
* SQL operation n */
DB::commit();
/* Transaction successful. */
}catch(\Exception $e){
DB::rollback();
/* Transaction failed. */
}