|
22 | 22 | use Symfony\Component\PropertyAccess\Exception\NoSuchIndexException;
|
23 | 23 | use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
|
24 | 24 | use Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException;
|
| 25 | +use Symfony\Component\PropertyAccess\Exception\UninitializedPropertyException; |
25 | 26 | use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
|
26 | 27 | use Symfony\Component\PropertyInfo\PropertyReadInfo;
|
27 | 28 | use Symfony\Component\PropertyInfo\PropertyReadInfoExtractorInterface;
|
@@ -389,14 +390,33 @@ private function readProperty(array $zval, string $property, bool $ignoreInvalid
|
389 | 390 | $name = $access->getName();
|
390 | 391 | $type = $access->getType();
|
391 | 392 |
|
392 |
| - if (PropertyReadInfo::TYPE_METHOD === $type) { |
393 |
| - $result[self::VALUE] = $object->$name(); |
394 |
| - } elseif (PropertyReadInfo::TYPE_PROPERTY === $type) { |
395 |
| - $result[self::VALUE] = $object->$name; |
| 393 | + try { |
| 394 | + if (PropertyReadInfo::TYPE_METHOD === $type) { |
| 395 | + try { |
| 396 | + $result[self::VALUE] = $object->$name(); |
| 397 | + } catch (\TypeError $e) { |
| 398 | + if (preg_match((sprintf('/^Return value of %s::%s\(\) must be of the type (\w+), null returned$/', preg_quote(\get_class($object)), $name)), $e->getMessage(), $matches)) { |
| 399 | + throw new UninitializedPropertyException(sprintf('The method "%s::%s()" returned "null", but expected type "%3$s". Have you forgotten to initialize a property or to make the return type nullable using "?%3$s" instead?', \get_class($object), $name, $matches[1]), 0, $e); |
| 400 | + } |
396 | 401 |
|
397 |
| - if (isset($zval[self::REF]) && $access->canBeReference()) { |
398 |
| - $result[self::REF] = &$object->$name; |
| 402 | + throw $e; |
| 403 | + } |
| 404 | + } elseif (PropertyReadInfo::TYPE_PROPERTY === $type) { |
| 405 | + $result[self::VALUE] = $object->$name; |
| 406 | + |
| 407 | + if (isset($zval[self::REF]) && $access->canBeReference()) { |
| 408 | + $result[self::REF] = &$object->$name; |
| 409 | + } |
399 | 410 | }
|
| 411 | + } catch (\Error $e) { |
| 412 | + // handle uninitialized properties in PHP >= 7.4 |
| 413 | + if (\PHP_VERSION_ID >= 70400 && preg_match('/^Typed property ([\w\\\]+)::\$(\w+) must not be accessed before initialization$/', $e->getMessage(), $matches)) { |
| 414 | + $r = new \ReflectionProperty($matches[1], $matches[2]); |
| 415 | + |
| 416 | + throw new UninitializedPropertyException(sprintf('The property "%s::$%s" is not readable because it is typed "%3$s". You should either initialize it or make it nullable using "?%3$s" instead.', $r->getDeclaringClass()->getName(), $r->getName(), $r->getType()->getName()), 0, $e); |
| 417 | + } |
| 418 | + |
| 419 | + throw $e; |
400 | 420 | }
|
401 | 421 | } elseif ($object instanceof \stdClass && property_exists($object, $property)) {
|
402 | 422 | $result[self::VALUE] = $object->$property;
|
|
0 commit comments