diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index 5d9298df7a52d..b9ef294d70403 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -482,11 +482,11 @@ private function readProperty(array $zval, string $property, bool $ignoreInvalid } } catch (\Error $e) { // handle uninitialized properties in PHP >= 7.4 - if (\PHP_VERSION_ID >= 70400 && preg_match('/^Typed property ([\w\\\]+)::\$(\w+) must not be accessed before initialization$/', $e->getMessage(), $matches)) { - $r = new \ReflectionProperty($matches[1], $matches[2]); + if (\PHP_VERSION_ID >= 70400 && preg_match('/^Typed property [\w@\\\]+::\$(\w+) must not be accessed before initialization$/', $e->getMessage(), $matches)) { + $r = new \ReflectionProperty($class, $matches[1]); $type = ($type = $r->getType()) instanceof \ReflectionNamedType ? $type->getName() : (string) $type; - throw new UninitializedPropertyException(sprintf('The property "%s::$%s" is not readable because it is typed "%s". You should initialize it or declare a default value instead.', $r->getDeclaringClass()->getName(), $r->getName(), $type), 0, $e); + throw new UninitializedPropertyException(sprintf('The property "%s::$%s" is not readable because it is typed "%s". You should initialize it or declare a default value instead.', !str_contains(\get_class($object), "@anonymous\0") ? $r->getDeclaringClass()->getName() : (get_parent_class($object) ?: key(class_implements($object)) ?: 'class').'@anonymous', $r->getName(), $type), 0, $e); } throw $e; diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php index 521218f671c75..5368c9670947d 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php @@ -206,6 +206,41 @@ public function getUninitialized(): array $this->propertyAccessor->getValue($object, 'uninitialized'); } + /** + * @requires PHP 7.4 + */ + public function testGetValueThrowsExceptionIfUninitializedNotNullablePropertyWithGetterOfAnonymousClass() + { + $this->expectException(UninitializedPropertyException::class); + $this->expectExceptionMessage('The property "class@anonymous::$uninitialized" is not readable because it is typed "string". You should initialize it or declare a default value instead.'); + + $object = eval('return new class() { + private string $uninitialized; + + public function getUninitialized(): string + { + return $this->uninitialized; + } + };'); + + $this->propertyAccessor->getValue($object, 'uninitialized'); + } + + /** + * @requires PHP 7.4 + */ + public function testGetValueThrowsExceptionIfUninitializedPropertyOfAnonymousClass() + { + $this->expectException(UninitializedPropertyException::class); + $this->expectExceptionMessage('The property "class@anonymous::$uninitialized" is not readable because it is typed "string". You should initialize it or declare a default value instead.'); + + $object = eval('return new class() { + public string $uninitialized; + };'); + + $this->propertyAccessor->getValue($object, 'uninitialized'); + } + public function testGetValueThrowsExceptionIfUninitializedPropertyWithGetterOfAnonymousStdClass() { $this->expectException(AccessException::class);