1616use Symfony \Component \HttpKernel \Exception \AccessDeniedHttpException ;
1717use Symfony \Component \HttpKernel \Exception \HttpExceptionInterface ;
1818use Symfony \Component \Security \Core \Exception \AccessDeniedException ;
19+ use Symfony \Component \Validator \ConstraintViolationInterface ;
20+ use Symfony \Component \Validator \Exception \ValidationFailedException ;
1921use Symfony \Component \Validator \Exception \ValidatorException ;
2022
2123class ExceptionListener
@@ -36,33 +38,73 @@ public function onKernelException(ExceptionEvent $event): void
3638 {
3739 $ exception = $ event ->getThrowable ();
3840
41+ if ($ exception instanceof ValidationFailedException) {
42+ $ event ->setResponse (
43+ new JsonResponse ([
44+ 'message ' => 'Validation failed ' ,
45+ 'errors ' => $ this ->formatViolations ($ exception ),
46+ ], 422 )
47+ );
48+
49+ return ;
50+ }
51+
3952 foreach (self ::EXCEPTION_STATUS_MAP as $ class => $ statusCode ) {
4053 if ($ exception instanceof $ class ) {
41- $ status = $ statusCode ?? $ exception ->getStatusCode ();
54+ $ status = $ statusCode ?? (
55+ method_exists ($ exception , 'getStatusCode ' )
56+ ? $ exception ->getStatusCode ()
57+ : 400
58+ );
59+
4260 $ event ->setResponse (
4361 new JsonResponse ([
44- 'message ' => $ exception ->getMessage ()
62+ 'message ' => $ exception ->getMessage (),
4563 ], $ status )
4664 );
65+
4766 return ;
4867 }
4968 }
5069
5170 if ($ exception instanceof HttpExceptionInterface) {
5271 $ event ->setResponse (
5372 new JsonResponse ([
54- 'message ' => $ exception ->getMessage ()
73+ 'message ' => $ exception ->getMessage (),
5574 ], $ exception ->getStatusCode ())
5675 );
76+
5777 return ;
5878 }
5979
6080 if ($ exception instanceof Exception) {
6181 $ event ->setResponse (
6282 new JsonResponse ([
63- 'message ' => $ exception ->getMessage ()
83+ 'message ' => $ exception ->getMessage (),
6484 ], 500 )
6585 );
6686 }
6787 }
88+
89+ /**
90+ * @return array<string, array<int, string>>
91+ */
92+ private function formatViolations (ValidationFailedException $ exception ): array
93+ {
94+ $ errors = [];
95+
96+ foreach ($ exception ->getViolations () as $ violation ) {
97+ /** @var ConstraintViolationInterface $violation */
98+ $ field = $ violation ->getPropertyPath ();
99+ $ message = $ violation ->getMessage ();
100+
101+ if ($ field === '' ) {
102+ $ field = '_global ' ;
103+ }
104+
105+ $ errors [$ field ][] = $ message ;
106+ }
107+
108+ return $ errors ;
109+ }
68110}
0 commit comments