Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitfea4b47

Browse files
committed
[HttpKernel] Merge PartialDenormalizationException errors and validation errors together
1 parent686aaf4 commitfea4b47

File tree

4 files changed

+68
-13
lines changed

4 files changed

+68
-13
lines changed

‎src/Symfony/Bundle/FrameworkBundle/Resources/config/web.php‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
->args([
6767
service('serializer'),
6868
service('validator')->nullOnInvalid(),
69+
service('translator')->nullOnInvalid(),
6970
])
7071
->tag('controller.targeted_value_resolver', ['name' => RequestPayloadValueResolver::class])
7172

‎src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php‎

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,13 @@
2424
useSymfony\Component\Serializer\Exception\UnsupportedFormatException;
2525
useSymfony\Component\Serializer\Normalizer\DenormalizerInterface;
2626
useSymfony\Component\Serializer\SerializerInterface;
27+
useSymfony\Component\Translation\IdentityTranslator;
28+
useSymfony\Component\Validator\ConstraintViolation;
2729
useSymfony\Component\Validator\ConstraintViolationInterface;
30+
useSymfony\Component\Validator\ConstraintViolationList;
2831
useSymfony\Component\Validator\Exception\ValidationFailedException;
2932
useSymfony\Component\Validator\Validator\ValidatorInterface;
33+
useSymfony\Contracts\Translation\TranslatorInterface;
3034

3135
/**
3236
* @author Konstantin Myakshin <molodchick@gmail.com>
@@ -51,7 +55,8 @@ final class RequestPayloadValueResolver implements ValueResolverInterface
5155

5256
publicfunction__construct(
5357
privatereadonlySerializerInterface&DenormalizerInterface$serializer,
54-
privatereadonly ?ValidatorInterface$validator,
58+
privatereadonly ?ValidatorInterface$validator =null,
59+
privatereadonly ?TranslatorInterface$translator =null,
5560
) {
5661
}
5762

@@ -71,14 +76,37 @@ public function resolve(Request $request, ArgumentMetadata $argument): iterable
7176
thrownew \LogicException(sprintf('Could not resolve the "$%s" controller argument: argument should be typed.',$argument->getName()));
7277
}
7378

74-
try {
75-
$payload =$this->$payloadMapper($request,$type,$attributes[0]);
76-
}catch (PartialDenormalizationException$e) {
77-
thrownewHttpException($validationFailedCode,implode("\n",array_map(staticfn (NotNormalizableValueException$e) =>$e->getMessage(),$e->getErrors())),$e);
78-
}
79-
80-
if (null !==$payload &&\count($violations =$this->validator?->validate($payload) ?? [])) {
81-
thrownewHttpException($validationFailedCode,implode("\n",array_map(staticfn (ConstraintViolationInterface$e) =>$e->getMessage(),iterator_to_array($violations))),newValidationFailedException($payload,$violations));
79+
if ($this->validator) {
80+
$violations =newConstraintViolationList();
81+
try {
82+
$payload =$this->$payloadMapper($request,$type,$attributes[0]);
83+
}catch (PartialDenormalizationException$e) {
84+
$trans =$this->translator ?$this->translator->trans(...) :fn ($m,$p) =>strtr($m,$p);
85+
foreach ($e->getErrors()as$error) {
86+
$parameters = ['{{ type }}' =>implode('|',$error->getExpectedTypes())];
87+
if ($error->canUseMessageForUser()) {
88+
$parameters['hint'] =$error->getMessage();
89+
}
90+
$template ='This value should be of type {{ type }}.';
91+
$message =$trans($template,$parameters,'validators');
92+
$violations->add(newConstraintViolation($message,$template,$parameters,null,$error->getPath(),null));
93+
}
94+
$payload =$e->getData();
95+
}
96+
97+
if (null !==$payload) {
98+
$violations->addAll($this->validator->validate($payload));
99+
}
100+
101+
if (\count($violations)) {
102+
thrownewHttpException($validationFailedCode,implode("\n",array_map(staticfn ($e) =>$e->getMessage(),iterator_to_array($violations))),newValidationFailedException($payload,$violations));
103+
}
104+
}else {
105+
try {
106+
$payload =$this->$payloadMapper($request,$type,$attributes[0]);
107+
}catch (PartialDenormalizationException$e) {
108+
thrownewHttpException($validationFailedCode,implode("\n",array_map(staticfn ($e) =>$e->getMessage(),$e->getErrors())),$e);
109+
}
82110
}
83111

84112
if (null !==$payload ||$argument->isNullable()) {

‎src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/RequestPayloadValueResolverTest.php‎

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
useSymfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
2020
useSymfony\Component\HttpKernel\Exception\HttpException;
2121
useSymfony\Component\Serializer\Encoder\JsonEncoder;
22+
useSymfony\Component\Serializer\Exception\PartialDenormalizationException;
2223
useSymfony\Component\Serializer\Normalizer\ObjectNormalizer;
2324
useSymfony\Component\Serializer\Serializer;
2425
useSymfony\Component\Validator\ConstraintViolation;
@@ -46,9 +47,29 @@ public function testNotTypedArgument()
4647
$resolver->resolve($request,$argument);
4748
}
4849

50+
publicfunctiontestWithoutValidatorAndCouldNotDenormalize()
51+
{
52+
$content ='{"price": 50, "title": ["not a string"]}';
53+
$serializer =newSerializer([newObjectNormalizer()], ['json' =>newJsonEncoder()]);
54+
55+
$resolver =newRequestPayloadValueResolver($serializer);
56+
57+
$argument =newArgumentMetadata('invalid', RequestPayload::class,false,false,null,false, [
58+
MapRequestPayload::class =>newMapRequestPayload(),
59+
]);
60+
$request = Request::create('/','POST', server: ['CONTENT_TYPE' =>'application/json'], content:$content);
61+
62+
try {
63+
$resolver->resolve($request,$argument);
64+
$this->fail(sprintf('Expected "%s" to be thrown.', HttpException::class));
65+
}catch (HttpException$e) {
66+
$this->assertInstanceOf(PartialDenormalizationException::class,$e->getPrevious());
67+
}
68+
}
69+
4970
publicfunctiontestValidationNotPassed()
5071
{
51-
$content ='{"price": 50}';
72+
$content ='{"price": 50, "title": ["not a string"]}';
5273
$payload =newRequestPayload(50);
5374
$serializer =newSerializer([newObjectNormalizer()], ['json' =>newJsonEncoder()]);
5475

@@ -69,15 +90,18 @@ public function testValidationNotPassed()
6990
$resolver->resolve($request,$argument);
7091
$this->fail(sprintf('Expected "%s" to be thrown.', HttpException::class));
7192
}catch (HttpException$e) {
72-
$this->assertInstanceOf(ValidationFailedException::class,$e->getPrevious());
93+
$validationFailedException =$e->getPrevious();
94+
$this->assertInstanceOf(ValidationFailedException::class,$validationFailedException);
95+
$this->assertSame('This value should be of type unknown.',$validationFailedException->getViolations()[0]->getMessage());
96+
$this->assertSame('Test',$validationFailedException->getViolations()[1]->getMessage());
7397
}
7498
}
7599

76100
publicfunctiontestUnsupportedMedia()
77101
{
78102
$serializer =newSerializer();
79103

80-
$resolver =newRequestPayloadValueResolver($serializer,null);
104+
$resolver =newRequestPayloadValueResolver($serializer);
81105

82106
$argument =newArgumentMetadata('invalid', \stdClass::class,false,false,null,false, [
83107
MapRequestPayload::class =>newMapRequestPayload(),
@@ -161,6 +185,8 @@ public function testRequestInputValidationPassed()
161185

162186
class RequestPayload
163187
{
188+
publicstring$title;
189+
164190
publicfunction__construct(publicreadonlyfloat$price)
165191
{
166192
}

‎src/Symfony/Component/HttpKernel/composer.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"symfony/finder":"^5.4|^6.0",
3737
"symfony/http-client-contracts":"^2.5|^3",
3838
"symfony/process":"^5.4|^6.0",
39-
"symfony/property-access":"^5.4|^6.0",
39+
"symfony/property-access":"^5.4.5|^6.0.5",
4040
"symfony/routing":"^5.4|^6.0",
4141
"symfony/serializer":"^6.3",
4242
"symfony/stopwatch":"^5.4|^6.0",

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp