Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[PropertyInfo] PhpStanExtractor is not correctly resolving types declared in traits #54569

Closed
@alexandre-le-borgne

Description

@alexandre-le-borgne

Symfony version(s) affected

7.0.6 (latest) and at least 6.4.3

Description

When I denormalize an array to a class,
If this class has a property declared in a trait whose type described in phpDoc is a class in the same namespace as the trait but not in the same namespace as the class, then I get this error :

image

PHP Fatal error: Uncaught Symfony\Component\Serializer\Exception\NotNormalizableValueException: The type of the "children" attribute for class "App\Example\Example" must be one of "App\Example\ExampleChild[]" ("array" given). in /home/aleborgne/Sites/bug-symfony-php-stan-extractor-traits/vendor/symfony/serializer/Exception/NotNormalizableValueException.php:32
Stack trace:
#0 /home/aleborgne/Sites/bug-symfony-php-stan-extractor-traits/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php(589): Symfony\Component\Serializer\Exception\NotNormalizableValueException::createForUnexpectedDataType()
#1 /home/aleborgne/Sites/bug-symfony-php-stan-extractor-traits/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php(358): Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer->validateAndDenormalize()
#2 /home/aleborgne/Sites/bug-symfony-php-stan-extractor-traits/vendor/symfony/serializer/Serializer.php(238): Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer->denormalize()
#3 /home/aleborgne/Sites/bug-symfony-php-stan-extractor-traits/index.php(55): Symfony\Component\Serializer\Serializer->denormalize()
#4 {main}
thrown in /home/aleborgne/Sites/bug-symfony-php-stan-extractor-traits/vendor/symfony/serializer/Exception/NotNormalizableValueException.php on line 32

How to reproduce

Clone https://github.com/alexandre-le-borgne/bug-symfony-php-stan-extractor-traits
and run php index.php

Dependencies:

    "php": ">=8.3",
    "symfony/property-info": "^7.0",
    "phpdocumentor/reflection-docblock": "^5.3",
    "symfony/serializer": "^7.0",
    "symfony/property-access": "^7.0"
<?php

use App\Example\Example;
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
use Symfony\Component\PropertyInfo\Extractor\PhpStanExtractor;
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;

require_once __DIR__ . '/vendor/autoload.php';

$phpDocExtractor = new PhpDocExtractor();
$phpStanExtractor = new PhpStanExtractor();
$reflectionExtractor = new ReflectionExtractor();

$listExtractors = [$reflectionExtractor];

$typeExtractors = [
    $phpStanExtractor, // Comment this line to avoid the bug
    $phpDocExtractor,
    $reflectionExtractor,
];

$descriptionExtractors = [$phpDocExtractor];
$accessExtractors = [$reflectionExtractor];
$propertyInitializableExtractors = [$reflectionExtractor];

$propertyInfo = new PropertyInfoExtractor(
    $listExtractors,
    $typeExtractors,
    $descriptionExtractors,
    $accessExtractors,
    $propertyInitializableExtractors
);

$properties = $propertyInfo->getTypes(Example::class, 'children');

// MUST returns ""App\Child\ExampleChild"" but it returns "App\Example\ExampleChild"
dump($properties[0]->getCollectionValueTypes()[0]->getClassName());

$normalizers = [
    new ArrayDenormalizer(),
    new ObjectNormalizer(propertyTypeExtractor: $propertyInfo),
];

$serializer = new Serializer($normalizers);

$result = $serializer->denormalize([
    'children' => [
        'testProperty' => '123',
    ],
], Example::class);

dump($result);

image

Possible Solution

Disable phpStanExtractor
Fix phpStanExtractor

Additional Context

It works when using only PhpDocExtractor

I think this bug was fixed in the PhpDocExtractor and then reintroduced when phpDocExtractor was replaced by PhpStanExtractor

The fix of PhpDocExtractor: #40175

The replacement of PhpDocExtractor by PhpStanExtractor: #40457

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions