Skip to content

AbstractItemNormalizer always returns array for collections? #2684

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();
    }
}

No activity

Activity on this issue will appear here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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