One of our customers needs sometimes a file uploaded on the checkout. In our other checkout posts, we explained, how to change the checkout and why it is so easy in Shopware <3
I don’t want to dive into details of the upload, if you want to read about it, leave a comment or drop us an email! I want to write about errors and validation, after diving with my colleague Bruno into it.
Create order
To create an order on Shopware, we have the CheckoutController::order
, the important part of the method looks like this:
// \Shopware\Storefront\Controller\CheckoutController::order #[Route(path: '/checkout/order', name: 'frontend.checkout.finish.order', options: ['seo' => false], methods: ['POST'])] public function order(RequestDataBag $data, SalesChannelContext $context, Request $request): Response { if (!$context->getCustomer()) { return $this->redirectToRoute('frontend.checkout.register.page'); } try { $this->addAffiliateTracking($data, $request->getSession()); $orderId = Profiler::trace('checkout-order', fn () => $this->orderService->createOrder($data, $context)); } catch (ConstraintViolationException $formViolations) { return $this->forwardToRoute('frontend.checkout.confirm.page', ['formViolations' => $formViolations]); } catch (InvalidCartException|Error|EmptyCartException) { $this->addCartErrors( $this->cartService->getCart($context->getToken(), $context) ); return $this->forwardToRoute('frontend.checkout.confirm.page'); } catch (UnknownPaymentMethodException|CartException $e) { if ($e->getErrorCode() === CartException::CART_PAYMENT_INVALID_ORDER_STORED_CODE && $e->getParameter('orderId')) { return $this->forwardToRoute('frontend.checkout.finish.page', ['orderId' => $e->getParameter('orderId'), 'changedPayment' => false, 'paymentFailed' => true]); } $message = $this->trans('error.' . $e->getErrorCode()); $this->addFlash('danger', $message); return $this->forwardToRoute('frontend.checkout.confirm.page'); } try { $finishUrl = $this->generateUrl('frontend.checkout.finish.page', ['orderId' => $orderId]); $errorUrl = $this->generateUrl('frontend.account.edit-order.page', ['orderId' => $orderId]); $response = Profiler::trace('handle-payment', fn (): ?RedirectResponse => $this->paymentService->handlePaymentByOrder($orderId, $data, $context, $finishUrl, $errorUrl)); return $response ?? new RedirectResponse($finishUrl); } catch (PaymentProcessException|InvalidOrderException|PaymentException|UnknownPaymentMethodException) { return $this->forwardToRoute('frontend.checkout.finish.page', ['orderId' => $orderId, 'changedPayment' => false, 'paymentFailed' => true]); } }
As you can see you have three catch blocks. The third is the important and interesting for us. But to use it, we need to make sure to NOT throw a
- ConstraintViolationException
- InvalidCartException
- EmptyCartException
- \Error
But throw a CartException
!
} catch (UnknownPaymentMethodException|CartException $e) { if ($e->getErrorCode() === CartException::CART_PAYMENT_INVALID_ORDER_STORED_CODE && $e->getParameter('orderId')) { return $this->forwardToRoute('frontend.checkout.finish.page', ['orderId' => $e->getParameter('orderId'), 'changedPayment' => false, 'paymentFailed' => true]); } $message = $this->trans('error.' . $e->getErrorCode()); $this->addFlash('danger', $message); return $this->forwardToRoute('frontend.checkout.confirm.page'); }
The easiest way to achieve the above conditions is to implement your own CartException
.
<?php namespace Agency\Project\Exception; class SomethingWentWrongOnCartValidationException extends \Shopware\Core\Checkout\Cart\CartException { public function __construct() { parent::__construct(0, 'SOMETHING_WENT_WRONG', 'Something went wrong.'); } }
This way you can easily throw new SomethingWentWrongOnCartValidationException()
anywhere during order creation in our case during CartConvertedEvent
.
Lost in Translation
As you can see above, then your exception is catch, the error code (in our example SOMETHING_WENT_WRONG
) is run through translation as error.SOMETHING_WENT_WRONG
, then added as flash message and the visitor is redirected back to the last step of the checkout.
One thought on “Shopware 6: Easy errors/validation on checkout and flash message”