Description
Symfony version(s) affected
<= 6.4 =>
Still present in latest stable release.
Description
Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor::getTypes
gives more priority to accessor and/or mutator methods over constructor definition even when it uses type hinting.
public function getTypes(string $class, string $property, array $context = []): ?array
{
if ($fromMutator = $this->extractFromMutator($class, $property)) {
return $fromMutator;
}
if ($fromAccessor = $this->extractFromAccessor($class, $property)) {
return $fromAccessor; // data suggesting 'bool' returned before extracting from constructor
}
if (
($context['enable_constructor_extraction'] ?? $this->enableConstructorExtraction)
&& $fromConstructor = $this->extractFromConstructor($class, $property)
) {
return $fromConstructor;
}
if ($fromPropertyDeclaration = $this->extractFromPropertyDeclaration($class, $property)) {
return $fromPropertyDeclaration;
}
return null;
}
How to reproduce
The problem could be reproduced for example when using Symfony Serializer:
We define a class which instantiates it's properties in the constructor and uses type hints there. We also add some method which could be classified as accessor or mutator by ReflectionExtractor
:
class SomeResponse
{
public function __construct(
#[SerializedName('url')]
public readonly ?string $url, // this type hint is ignored
) {
}
public function hasUrl(): bool // type is being detected from here
{
return !empty($this->url);
}
}
Now we try to deserialize simple JSON:
$serializer->deserialize(SomeResponse::class, '{"url": "http://test"}');
We'll get this error in the exception:
The type of the "url" attribute for class "SomeResponse" must be one of "bool" ("string" given).
Possible Solution
Maybe check if we can detect the type from constructor and if so, use it as a more reliable source.
Additional Context
No response