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

Commitdc04b8c

Browse files
bug#44295 [Serializer] fix support for lazy/unset properties (nicolas-grekas)
This PR was merged into the 4.4 branch.Discussion----------[Serializer] fix support for lazy/unset properties| Q | A| ------------- | ---| Branch? | 4.4| Bug fix? | yes| New feature? | no| Deprecations? | no| Tickets |Fix#44273#44283| License | MIT| Doc PR | -This basically backports#43469 into 4.4, which is the way to go tofix#44273.The code that exists to handle uninitialized properties is broken anyway (it was before the recent changes.)Commits-------db043aa [Serializer] fix support for lazy/unset properties
2 parents0796087 +db043aa commitdc04b8c

File tree

5 files changed

+55
-19
lines changed

5 files changed

+55
-19
lines changed

‎src/Symfony/Component/PropertyAccess/PropertyAccessor.php‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,7 @@ private function readProperty(array $zval, string $property, bool $ignoreInvalid
385385

386386
$result =self::RESULT_PROTO;
387387
$object =$zval[self::VALUE];
388+
$class =\get_class($object);
388389
$access =$this->getReadAccessInfo(\get_class($object),$property);
389390

390391
try {
@@ -406,6 +407,11 @@ private function readProperty(array $zval, string $property, bool $ignoreInvalid
406407
throw$e;
407408
}
408409
}elseif (self::ACCESS_TYPE_PROPERTY ===$access[self::ACCESS_TYPE]) {
410+
$name =$access[self::ACCESS_NAME];
411+
if (!method_exists($object,'__get') && !isset($object->$name) && !\array_key_exists($name, (array)$object) && (\PHP_VERSION_ID <70400 || !(new \ReflectionProperty($class,$name))->hasType())) {
412+
thrownewAccessException(sprintf('The property "%s::$%s" is not initialized.',$class,$name));
413+
}
414+
409415
$result[self::VALUE] =$object->{$access[self::ACCESS_NAME]};
410416

411417
if ($access[self::ACCESS_REF] &&isset($zval[self::REF])) {

‎src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php‎

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespaceSymfony\Component\Serializer\Normalizer;
1313

14+
useSymfony\Component\PropertyAccess\Exception\AccessException;
1415
useSymfony\Component\PropertyAccess\Exception\InvalidArgumentException;
1516
useSymfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
1617
useSymfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
@@ -181,7 +182,23 @@ public function normalize($object, $format = null, array $context = [])
181182
continue;
182183
}
183184

184-
$attributeValue =$this->getAttributeValue($object,$attribute,$format,$context);
185+
try {
186+
$attributeValue =$this->getAttributeValue($object,$attribute,$format,$context);
187+
}catch (AccessException$e) {
188+
if (sprintf('The property "%s::$%s" is not initialized.',\get_class($object),$attribute) ===$e->getMessage()) {
189+
continue;
190+
}
191+
if (($p =$e->getPrevious()) &&'Error' ===\get_class($p) &&$this->isUninitializedValueError($p)) {
192+
continue;
193+
}
194+
throw$e;
195+
}catch (\Error$e) {
196+
if ($this->isUninitializedValueError($e)) {
197+
continue;
198+
}
199+
throw$e;
200+
}
201+
185202
if ($maxDepthReached) {
186203
$attributeValue =$maxDepthHandler($attributeValue,$object,$attribute,$format,$context);
187204
}
@@ -637,4 +654,15 @@ private function getCacheKey(?string $format, array $context)
637654
returnfalse;
638655
}
639656
}
657+
658+
/**
659+
* This error may occur when specific object normalizer implementation gets attribute value
660+
* by accessing a public uninitialized property or by calling a method accessing such property.
661+
*/
662+
privatefunctionisUninitializedValueError(\Error$e):bool
663+
{
664+
return \PHP_VERSION_ID >=70400
665+
&&str_starts_with($e->getMessage(),'Typed property')
666+
&&str_ends_with($e->getMessage(),'must not be accessed before initialization');
667+
}
640668
}

‎src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php‎

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,16 +104,8 @@ protected function extractAttributes($object, $format = null, array $context = [
104104
}
105105

106106
// properties
107-
$propertyValues = !method_exists($object,'__get') ? (array)$object :null;
108107
foreach ($reflClass->getProperties()as$reflProperty) {
109-
if (null !==$propertyValues && !\array_key_exists($reflProperty->name,$propertyValues)) {
110-
if ($reflProperty->isPublic()
111-
|| ($reflProperty->isProtected() && !\array_key_exists("\0*\0{$reflProperty->name}",$propertyValues))
112-
|| ($reflProperty->isPrivate() && !\array_key_exists("\0{$reflProperty->class}\0{$reflProperty->name}",$propertyValues))
113-
) {
114-
unset($attributes[$reflProperty->name]);
115-
}
116-
108+
if (!$reflProperty->isPublic()) {
117109
continue;
118110
}
119111

‎src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php‎

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespaceSymfony\Component\Serializer\Normalizer;
1313

14+
useSymfony\Component\PropertyAccess\Exception\AccessException;
15+
1416
/**
1517
* Converts between objects and arrays by mapping properties.
1618
*
@@ -101,17 +103,10 @@ protected function extractAttributes($object, $format = null, array $context = [
101103
{
102104
$reflectionObject =new \ReflectionObject($object);
103105
$attributes = [];
104-
$propertyValues = !method_exists($object,'__get') ? (array)$object :null;
105106

106107
do {
107108
foreach ($reflectionObject->getProperties()as$property) {
108-
if ((null !==$propertyValues && (
109-
($property->isPublic() && !\array_key_exists($property->name,$propertyValues))
110-
|| ($property->isProtected() && !\array_key_exists("\0*\0{$property->name}",$propertyValues))
111-
|| ($property->isPrivate() && !\array_key_exists("\0{$property->class}\0{$property->name}",$propertyValues))
112-
))
113-
|| !$this->isAllowedAttribute($reflectionObject->getName(),$property->name,$format,$context)
114-
) {
109+
if (!$this->isAllowedAttribute($reflectionObject->getName(),$property->name,$format,$context)) {
115110
continue;
116111
}
117112

@@ -138,6 +133,21 @@ protected function getAttributeValue($object, $attribute, $format = null, array
138133
$reflectionProperty->setAccessible(true);
139134
}
140135

136+
if (\PHP_VERSION_ID >=70400 &&$reflectionProperty->hasType()) {
137+
return$reflectionProperty->getValue($object);
138+
}
139+
140+
if (!method_exists($object,'__get') && !isset($object->$attribute)) {
141+
$propertyValues = (array)$object;
142+
143+
if (($reflectionProperty->isPublic() && !\array_key_exists($reflectionProperty->name,$propertyValues))
144+
|| ($reflectionProperty->isProtected() && !\array_key_exists("\0*\0{$reflectionProperty->name}",$propertyValues))
145+
|| ($reflectionProperty->isPrivate() && !\array_key_exists("\0{$reflectionProperty->class}\0{$reflectionProperty->name}",$propertyValues))
146+
) {
147+
thrownewAccessException(sprintf('The property "%s::$%s" is not initialized.',\get_class($object),$reflectionProperty->name));
148+
}
149+
}
150+
141151
return$reflectionProperty->getValue($object);
142152
}
143153

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"symfony/error-handler":"^4.4|^5.0",
3030
"symfony/http-foundation":"^3.4|^4.0|^5.0",
3131
"symfony/mime":"^4.4|^5.0",
32-
"symfony/property-access":"^3.4.41|^4.4.9|^5.0.9",
32+
"symfony/property-access":"^4.4.36|^5.3.13",
3333
"symfony/property-info":"^3.4.13|~4.0|^5.0",
3434
"symfony/validator":"^3.4|^4.0|^5.0",
3535
"symfony/yaml":"^3.4|^4.0|^5.0"

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp