Skip to content

AbstractItemNormalizer always returns array for collections? #2684

Closed
@mvscheidt

Description

@mvscheidt

Is it by design that ApiPlatform is meant to always pass Collections as array, e.g. when submitting to the POST Endpoint?

According to the code yes, but is this intended? https://github.com/api-platform/core/blob/master/src/Serializer/AbstractItemNormalizer.php#L397

To paraphrase the error I got:

Argument n passed to App\\Entity\\Product::__construct() must be an instance of App\\Collection\\PriceCollection, array given - (it is passing me an array of Prices, but I need the Prices inside a PriceCollection)

This wouldn't be a problem if I could use a custom Item Denormalizer to create the PriceCollection, but I cant with 2.4.2 anymore.

In 2.4.2 I never even see PriceCollection reach the "supportsDenormalization" method of my Normalizer.

As soon as I downgrade from 2.4.2 to 2.3.6 my custom Denormalizer "works" again.

With 2.3.6 the PriceCollection reaches the Normalizer and submitting to "POST" works.

Could be related to #2662 ? (not sure though)

I already tried #2679 but it didn't do anything in my case, unless I missed something.


In the simplified php code (I left out most Annotations, this is mostly to exemplify the way it is setup) below ApiPlatform always passes "array" to the Product Constructor while ProductCollection is expected.

Note Product and Price are Entities/ Resources. PriceCollection however is not (it's just a simple object to ensure only entities of Type Price are actually passed to Product)

class PriceCollection
{
    /** @var ArrayCollection Doctrine ArrayCollection */
    private $prices;

    public function __construct(Price ...$prices)
    {
        $this->prices = new ArrayCollection($prices);
    }

    public function getPrices(): ArrayCollection
    {
        return $this->prices;
    }
}
class Product
{
    /**
     * @var Collection
     * @ApiSubresource()
     * @ORM\ManyToMany(targetEntity="Price", cascade={"persist", "remove"})
     * @ORM\JoinTable(name="product_prices",
     *      joinColumns={@ORM\JoinColumn(name="product_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="price_id", referencedColumnName="id", unique=true)}
     *      )
     */
    private $prices;

    public function __construct($paramA, PriceCollection $prices, $otherParam)
    {
        ...
        $this->prices = $prices->getPrices();
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions