Русское сообщество разработки на PHP-фреймворке Laravel.
Ты не вошёл. Вход тут.
Страницы 1
Laravel: 5.4.24
MySQL: 5.7.17 (InnoDB)
Привет всем! Посмотрел описание работы с транзакциями в документации Laravel. Там подробно расписано как действовать, взаимодействуя с БД через фасад DB, но примеров использования транзакций с Eloquent ORM там не нашел. Указано только, что с ним тоже можно работать, используя инструменты DB фасада.
Попробывал набросать код, следуя интуиции:
/**
* Create a new user instance after a valid registration.
*
* @param array $data
* @return User
*/
protected function create(array $data)
{
$user = null;
try{
DB::beginTransaction();
// Create a user record
$user = User::create([
'name' => $data['reg_fname'].' '.$data['reg_lname'],
'email' => $data['reg_email'],
'password' => bcrypt($data['reg_password']),
]);
// Add a profile to the user
$user->profile()->save(new UserProfile([
'fname' => $data['reg_fname'],
'lname' => $data['reg_lname']
]));
DB::commit();
} catch(\Exception $exception){
DB::rollBack();
// Allow Laravel engine to handle this exception
throw $exception;
}
return $user;
}
Тут создается сначала запись в таблице users, а затем добавляется запись в таблицу user_profiles. Все происходит внутри одной транзакции.
Проверил, вроде все работает как надо. При ошибке добавления записи в user_profiles, отменяется запись в таблицу users.
Вопросы: всё ли я делаю правильно? Можно ли и дальше в проекте использовать такой подход? Нет ли каких подводных камней?
Прошу, наведите на путь истинный, ибо не ведаю что творю, добро или зло. Не хотелось бы, чтобы в конце проекта настигла кара небесная
Не в сети
можно лучше
\DB::transaction(function () { … });
– при этом транзакция автоматически отменяется если внутри в коде будет выброшен любой эксепшен. более того – бросание эксепшена является стандартным средством отмены транзакции. если код выполнился без ошибок – транзакция будет закоммичена. снаружи полагается завернуть это добро в try … catch и обрабатывать ошибки
ещё если тебе нужны блокировки на отдельных записях (например – изменение баланса пользователя при покупке) обрати внимание на row-based locks в innodb. на элоквенте (и вообще на всех запросах построителя) это делается добавлением ->forUpdate. соответствует синтаксису SELECT … FOR UPDATE (есть в mysql и во всех других коннекторах ларавеля кроме sqlite). блокировка работает только внутри транзакции и автоматически снимается когда транзакция коммитится или откатывается
ещё в ларавеле можно открывать транзакцию внутри транзакции – базы такое конечно не все поддерживают (mysql – точно нет), поэтому ларавель использует внутренний счётчик чтобы отслеживать количество beginTransaction – когда последняя транзакция закрывается, тогда выполняется коммит. это даёт возможность внутри \DB::transaction() вызывать любой другой код, который тоже может использовать транзакции в своей работе.
Не в сети
Не в сети
Страницы 1