Я попытался решить проблему с многократным нажатием кнопки отправки с помощью ReCaptcha V3. Это вроде работает, поскольку вставка базы данных выполняется в контроллере только один раз, а в последующие раз она просто попадает в проверку, возвращая ошибку.
Проблема в том, что метод контроллера не выполняется полностью.
Например, если я несколько раз нажимаю кнопку отправки на странице электронной коммерции, в CheckoutController метод checkout не запускается полностью.
class CheckOutController extends Controller {
public function checkout(Request $request) {
// Some checkout Logic (insert into database)
$this->validate($request, [
'recaptcha' => ['required', new \App\Rules\Recaptcha]
]);
if (Cart::content()->count() > 0) {
foreach (Cart::content() as $cartItem) {
$insert = new \App\Transaction;
$insert->product_id = $cartItem->id;
$insert->receipt_id = $cartItem->receipt_id;
$insert->quantity = $cartItem->qty;
$insert->price= $cartItem->price;
$insert->save();
}
Cart::destroy(); //last part of checkout logic
return view('finishCheckout');
}
return abort(404);
}
}
Поскольку я работаю локально, скорость выше, поэтому запрос повторяется через мой код, вставляя данные в мою базу данных.
Иногда запрос попадает в часть логики Cart:: destroy();, иногда - нет. Но я подозреваю, что в производственной среде код может остановиться в другом месте перед этой частью.
И он никогда не попадает в return view('finishCheckout');. Он просто повторяет тот же метод и не проходит проверку, возвращая меня обратно на страницу оформления заказа с ошибкой проверки.
Могу ли я что-нибудь сделать, чтобы убедиться, что либо весь метод запущен, либо полностью остановить его?
Редактировать: Обратите внимание, что это происходит только тогда, когда я нажимаю кнопку отправки несколько раз! Если бы я щелкнул по нему только один раз, метод работает правильно.
Я работаю с APP_DEBUG=true, но у меня нет ошибок в laravel.log относительно этого контроллера.
Не уверен, что это связано с вашей проблемой, но Cart::destroy; недействителен. Если вы собираетесь вызвать статический метод destroy, тогда вы хотите сделать Cart::destroy();
Да, в моем коде есть Cart::destroy(). Я написал это здесь неправильно, извините.
Было бы полезно, если бы вы могли поделиться кодом, который не работает или, просто добавьте много журналов после каждой строки, чтобы определить, что запускается и где останавливается.
Я написал код, который не работает. Только Cart::destroy(); //last part of checkout logic return view('finishCheckout'); выходит из строя, а все остальное работает правильно. И Cart :: destroy () дает сбой только иногда и не всегда.






Перед удалением use \Cart
Можно использовать Cart::delete() or Cart::where(....)->delete()
destroy()delete(), как бы вы ни называли его, не является проблемой. Иногда этот метод (destroy() в моем случае) работает, иногда нет. Но это не ошибка метода, после нескольких отправок формы запрос не ждет завершения метода и вместо этого выполняет новый запрос. Если бы мне нужно было сделать только один щелчок по кнопке отправки, метод checkout работает правильно.
Может быть, корзина пуста
Cart::destroy(); - это команда пустой корзины, и она не работает, когда я нажимаю кнопку отправки несколько раз. Работает только если щелкнуть один раз.
Лучшим решением было бы предотвратить двойной щелчок на стороне клиента. сделать функцию javascript, которая onSubmit отключает кнопку отправки.
Таким образом, пользователь получит ответ на первый сделанный им вызов, а не на последний (в случае двойной отправки).
Кстати, вы можете имитировать медленный сервер. просто добавьте sleep(3) в начало метода контроллера.
С sleep(3) у меня такая же проблема: код не работает в одной строке, НО только при отправке нескольких форм. Я хотел узнать, почему это происходит, прежде чем пытаться решить эту проблему на стороне клиента.
Первый запрос: checkout_logic + cart_destroy. Второй запрос: checkout_logic_with_no_cart (потому что он был уничтожен) -> ошибка
Первый запрос не выполняет cart_destroy, когда я нажимаю кнопки отправки несколько раз. Вот в чем проблема. Если я нажму кнопку отправки, как только он правильно выполнит cart_destroy.
@Victordb то, что вы говорите, противоречиво, можете ли вы указать на свой вопрос полный код checkout?
Я добавил кое-что, имеющее отношение к вопросу. Хотя это не проблема с кодом, поскольку он отлично работает, когда я отправляю форму только один раз. Проблема в том, что я нажимаю кнопки отправки несколько раз.
Как я уже сказал, результат, который вы получаете при многократной отправке, - это последний запрос (404 100%). первый работал правильно.
Первый не выполняет Cart::destroy();. У меня все еще есть продукты в тележке, когда меня перенаправляют обратно с ошибкой проверки. Когда я отправляю форму одним щелчком мыши, Cart::destroy(); правильно опорожняет корзину. Но когда я отправляю с несколькими щелчками мыши, Cart::destroy(); происходит не только с кодом над ним.
Позвольте нам продолжить обсуждение в чате.
Моя теория заключается в том, что, поскольку вы нажимаете кнопку несколько раз, в одном из запросов он выполняет итерацию по содержимому корзины, а затем достигает метода Cart::destroy(), но затем по другим запросам, поскольку это уже было так, он не выполняет условное и прыгает прямо к функции abort(404).
Если вы делаете запрос с помощью Ajax, меня это не удивляет. В случае асинхронных HTTP-запросов, если вы снова нажмете кнопку, он создаст новый запрос и позволит продолжить выполнение предыдущего, а не отменит его. Это должен быть ваш внешний интерфейс, который при нажатии кнопки во время выполнения запроса отключает кнопку, поэтому дальнейшие запросы не могут быть выполнены.
Я не делаю запрос с помощью Ajax, и проблема в том, что первый запрос ОСТАНАВЛИВАЕТСЯ прямо перед Cart::destroy(). Таким образом, первый запрос проходит через код (вставляется в базу данных) и по какой-то причине останавливается прямо на Cart::destroy().
Возможно возникновение исключения. Проверьте журналы и посмотрите, есть ли там что-нибудь. Вы также можете обернуть вставки в транзакцию базы данных, чтобы в случае исключения она возвращала вставки базы данных.
Решено с использованием транзакций php, например:
class CheckOutController extends Controller {
public function checkout(Request $request) {
// Some checkout Logic (insert into database)
$this->validate($request, [
'recaptcha' => ['required', new \App\Rules\Recaptcha]
]);
DB::beginTransaction();
try {
if (Cart::content()->count() > 0) {
foreach (Cart::content() as $cartItem) {
$insert = new \App\Transaction;
$insert->product_id = $cartItem->id;
$insert->receipt_id = $cartItem->receipt_id;
$insert->quantity = $cartItem->qty;
$insert->price= $cartItem->price;
$insert->save();
}
}
DB::commit();
Cart::destroy();
return view('finishCheckout');
} catch (\Exception $e) {
DB::rollback();
return view('errorView')->withErrors($e->getMessage());
}
return abort(404);
}
}
Какие-нибудь ошибки зарегистрированы где-нибудь?