<?php
namespace App\Exception;
use App\Helper\GeneralHelper;
use Exception;
use Throwable;
class FormRequestException extends Exception
{
private $errors;
public function __construct($errors, $code = 0, Throwable $previous = null)
{
parent::__construct("Form Request Error", $code, $previous);
$this->errors = $errors;
}
public function getErrors()
{
return $this->errors;
}
public function getErrorMessages(): array
{
$messages = [];
foreach ($this->errors as $error){
$messages[$error->getPropertyPath()][] = $error->getMessage();
}
return $messages;
}
}
<?php
namespace App\FormRequest;
use App\Exception\FormRequestException;
use App\Helper\GeneralHelper;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Validator\ValidatorInterface;
class BaseRequest
{
private ValidatorInterface $validator;
private $attributes;
private $errors;
public function __construct(RequestStack $request, ValidatorInterface $validator)
{
$this->validator = $validator;
$this->attributes = json_decode($request->getCurrentRequest()->getContent(), true);
$this->validate();
$this->hasError();
}
public function validate()
{
$this->errors = $this->validator->validate($this->attributes, $this->getRules());
}
public function getRules(): Assert\Collection
{
return new Assert\Collection([]);
}
public function hasError()
{
if(count($this->errors) > 0){
throw new FormRequestException($this->errors);
}
}
public function all(): array
{
return $this->attributes;
}
}
<?php
namespace App\FormRequest;
use Symfony\Component\Validator\Constraints as Assert;
class OrderProductStoreRequest extends BaseRequest
{
public function getRules(): Assert\Collection
{
return new Assert\Collection([
'product_id' => [
new Assert\NotBlank(),
new Assert\Type('integer'),
],
'quantity' => [
new Assert\NotBlank(),
new Assert\Type('integer'),
]
]);
}
}
public function storeProduct(OrderProductStoreRequest $request): JsonResponse
{
$status = $this->orderService->storeProduct($request->all());
}
<?php
namespace App\EventSubscriber;
use App\Exception\FormRequestException;
use App\Helper\RedirectHelper;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Exception\HttpException;
class ExceptionSubscriber implements EventSubscriberInterface
{
public function onKernelException(ExceptionEvent $event): void
{
if ($event->getThrowable() instanceof HttpException) {
$event->setResponse(RedirectHelper::badRequest([], $event->getThrowable()->getMessage()));
} else if ($event->getThrowable() instanceof FormRequestException) {
$event->setResponse(RedirectHelper::badRequest($event->getThrowable()->getErrorMessages()));
} else {
$event->setResponse(RedirectHelper::internalServerError([
'code' => $event->getThrowable()->getCode(),
'file' => $event->getThrowable()->getFile(),
'line' => $event->getThrowable()->getLine(),
],
$event->getThrowable()->getMessage()
));
}
}
public static function getSubscribedEvents(): array
{
return [
'kernel.exception' => 'onKernelException',
];
}
}