#php #mysql #laravel #pdo
#php #mysql #laravel #pdo
Вопрос:
Мне нужны идеи для решения проблемы, когда есть заказ, который нужно обновить, и платежи, которые должны быть созданы для этого заказа. Но если поручение не выполняется. Обновления, внесенные в заказ, должны быть отменены, но созданные для него платежи должны сохраняться.
Пример кода контроллера:
$order = Order::find(1);
DB::beginTransaction();
try {
$order->update(['status' => 1]);
chargeOrder ($order);
} catch (PaymentErrorException $e) {
DB::rollback();
throw $e;
}
catch (Exception $e) {
DB::rollback();
throw $e;
}
DB::commit();
Пример функции, которая производит начисление заказа:
function chargeOrder( $order ) {
$payments_service->charge($order);
$order->payments()->create( new Payment() );
}
Что мне нужно, так это то, что при возникновении исключения PaymentErrorException следует отменить только $order-> update(), но изменения, внесенные внутри функции chargeOrder, должны сохраняться.
Комментарии:
1. Вы имеете в виду функцию «CreateOrder», которой нет. Вы имеете в виду «chargeOrder»?. Вообще говоря, у вас есть шанс «исправить» вещи в catch-area. Это место для отмены обновления. Но у вас проблема в том, что вы не знаете, где произошло исключение. Если это произошло до «chargeOrder», изменения не сохраняются, потому что они никогда не происходят.
2. 1 — Да, это chargeOrder. 2 — Это просто пример кода, объясняющий проблему в двух словах. В примере исключение PaymentErrorException возникнет внутри chargeOrder(), если что-то не так произошло во время процесса начисления.
3. Не могли бы вы просто использовать новое соединение, чтобы сделать chargeOrder?
4. @madz Я думаю, что это альтернатива, нужно попробовать. Но если бы я мог справиться с этим без создания нового соединения, было бы лучше.
5. Не было бы лучше запустить chargeOrder, зафиксировать эти изменения, а затем запустить обновление и зафиксировать их отдельно? Я бы подумал, что если платежи всегда должны применяться, несмотря ни на что, то лучше рассматривать их как две отдельные транзакции
Ответ №1:
Если я правильно понимаю вопрос:
$order = Order::find(1);
$previousStatus = $order->status;
DB::beginTransaction();
try {
$order->update(['status' => 1]);
chargeOrder ($order);
} catch (PaymentErrorException $e) {
$order->update(['status' => $previousStatus]);
}
catch (Exception $e) {
DB::rollback();
throw $e;
}
DB::commit();
Комментарии:
1. Спасибо за воспроизведение, это работает, но это как раз то, чего я должен избегать. Реальный код обновляет многие модели, и откат их вручную был бы плохим решением : (