Description
API Platform version(s) affected: x.y.z
4.1.17
Description
When a constructor argument gets defined that has the same name as the class's field, in which the constructor argument gets used to instantiate values in the constructor, the OpenAPI docs then type the field as array<string>
items while they actually should be typed as the classes that just were instantiated.
How to reproduce
The collection is fairly straight forward
class Foo {
# ...
#[ORM\OneToMany(targetEntity: Bar::class, mappedBy: 'foo', fetch: 'EXTRA_LAZY')]
#[ORM\OrderBy(['level' => 'ASC'])]
public Collection $bars;
public __construct(array $bars)
{
$this->bars = new ArrayCollection(array_map( ... , $bars));
}
And when the constructor argument is named differently, the bar
field on foo
is correctly documented as object with it's related fields again:
class Foo
{
/**
* @var Bar[]
*/
#[ORM\OneToMany(targetEntity: PackagingLayer::class, mappedBy: 'packagingHierarchy', fetch: 'EXTRA_LAZY')]
public Collection $bars;
public function __construct(
- array $bars,
+ array $inputBars,
) {
- $this->bars = new ArrayCollection(array_map( ... , $bars));
+ $this->bars = new ArrayCollection(array_map( ... , $inputBars));
}
}
Possible Solution
The typing of the class field should take precedence over the typing of the constructor parameter. Especially as the constructor parameter won't be available after construction, which is how it will be read by APIP. That makes this classify as bug.
Renaming the constructor argument is a workaround for this, as the argument then doesn't relate to the class field anymore.
Additional Context
Probably this is related to an earlier change for promoted properties. That check should be enhanced, by adding a check whether that constructor argument actually does have a class field with the same name. The class field should then be used over the constructor parameter.
[...] is Bar also a resource?
see #6173
I've tested this by either attributing both classes or none of the classes as ApiResource, but that does not change the behavior. The Foo class is a field on another entity (let's call it Baz), which is an ApiResource, so on normalization these three layers should result in a json graph like Baz -> Foo -> Bar[]