-
-
Notifications
You must be signed in to change notification settings - Fork 9.7k
Description
Description
In the serialization process with the symfony/serializer
it's common to define the PhpDocExtractor
as part of the PropertyNormalizer
. With the PhpDocExtractor
it's possible to have the following PHPDoc block on our properties:
<?php
final class Company
{
/**
* @var Employee[]
*/
public array $employees;
/**
* @param Employee[] $employees
*/
public function __construct(array $employees)
{
$this->employees = $employees;
}
}
final class Employee
{
public string $firstName;
public string $lastName;
public function __construct(
string $firstName,
string $lastName
) {
$this->firstName = $firstName;
$this->lastName = $lastName;
}
}
When supplying the following JSON, the objects are deserialized:
{
"employees": [
{
"firstName": "Max",
"lastName": "Mustermann"
},
{
"firstName": "Clara",
"lastName": "Carlston"
}
]
}
An alternative Annotation would be the usage of list<Employee>
. Which has the following advantages:
- It contains more information as
array<Employee>
(the key is an int) - It contains more information then
array<int, Employee>
(the key has to start with 0 and has no missing steps)
list<...>
is supported by Psalm, PHPStan and PHPStorm, but isn't by the PhpDocExtractor
. When used with the serializer, it result's in a ReflectionException
with Class App\...\list does not exist
.
I searched through the logic used and found the following snippet in PhpDocTypeHelper:
if (0 === strpos($docType, 'array<') && $type instanceof Array_) {
// array<value> is converted to x[] which is handled above
// so it's only necessary to handle array<key, value> here
$collectionKeyType = $this->getTypes($type->getKeyType())[0];
$collectionValueTypes = $this->getTypes($type->getValueType());
if (\count($collectionValueTypes) != 1) {
// the Type class does not support union types yet, so assume that no type was defined
$collectionValueType = null;
} else {
$collectionValueType = $collectionValueTypes[0];
}
return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, $collectionKeyType, $collectionValueType);
}
It's my understanding, that it would be enough to extend that with the list
type like the following:
if ((0 === strpos($docType, 'array<') || 0 === strpos($docType, 'list<')) && $type instanceof Array_) {
But I'm not 100% sure.
Would it be possible to extend it like this?
If so, would be happy to supply the Pull Request for it.