core icon indicating copy to clipboard operation
core copied to clipboard

PUT or PATCH with null values doesn't clear the value of nullable ManyToOne property of ORM entity

Open VictorKrasnov opened this issue 1 year ago • 1 comments

API Platform version(s) affected: 3.3.2

Description
If you have some ORM entity with ManyToOne relation, no way to clear this relations. Or I can't find this possibility.

How to reproduce

  1. Add entity like this:
#[ORM\Entity(repositoryClass: OrderRepository::class)]
#[ORM\Table('orders')]
class Order
{
    # ..... other properties is here

    #[ORM\ManyToOne(targetEntity: ...)]
    #[ORM\JoinColumn(nullable: true)]
    #[Groups(...)]
    protected ?TradingContractInterface $tradingContract = null;

    public function getTradingContract(): ?TradingContractInterface
    {
        return $this->tradingContract;
    }

    public function setTradingContract(?TradingContractInterface $tradingContract = null): static
    {
        $this->tradingContract = $tradingContract;
        return $this;
    }
}
  1. Publish REST methods with API Platform (in my case I did it with yaml):
resources:
  App\Order:
    shortName: Order
    description: Order entity.
    operations:
      - class: ApiPlatform\Metadata\GetCollection
        uriTemplate: /orders
        normalizationContext: { groups: ['order:list', 'reference'] }
        createdAt:
          createdAt: 'DESC'
        paginationItemsPerPage: 20
      - class: ApiPlatform\Metadata\Get
        uriTemplate: /orders/{id}
        normalizationContext: { groups: ['order:read', 'reference'] }
      - class: ApiPlatform\Metadata\Post
        uriTemplate: /orders
        normalizationContext: { groups: ['order:read', 'reference'] }
        denormalizationContext: { groups: ['order:create'] }
        processor: Ecomla\SalesBundle\ApiPlatform\State\Order\OrderCreateProcessor
      - class: ApiPlatform\Metadata\Patch
        uriTemplate: /admin/orders/{id}
        normalizationContext: { groups: ['order:read', 'reference'] }
        denormalizationContext: { groups: ['order:update', 'reference'] }
        processor: Ecomla\SalesBundle\ApiPlatform\State\Order\OrderUpdateProcessor
      - class: ApiPlatform\Metadata\Put
        uriTemplate: /admin/orders/{id}
        normalizationContext: { groups: ['order:read', 'reference'] }
        denormalizationContext: { groups: ['order:update', 'reference'] }
        processor: Ecomla\SalesBundle\ApiPlatform\State\Order\OrderUpdateProcessor
      - class: ApiPlatform\Metadata\Delete
        uriTemplate: /admin/orders/{id}
        normalizationContext: { groups: ['order:read', 'reference'] }
    routePrefix: ....

  1. Try to update entity with PATCH or PUT /admin/orders/{id} with json like:
{
   # ...other properties
   tradingContract: null
}

Expected behaviour: PATCH and PUT methods should clear current value of property tradingContract end return json without tradingContract property (due to skip_null_values option with value true passed to normaliser).

Actual behaviour: Property did not set to null, and the response includes property tradingContract with old data.

Possible Solution
I think you should change current logic of default denormaliser or add some config options to switch this behaviour.

VictorKrasnov avatar Jul 31 '24 15:07 VictorKrasnov

Can't you set skip_null_values to false in the denormalizer context? Maybe that it should be the default during denormalization (@dunglas)

soyuka avatar Aug 08 '24 14:08 soyuka

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Oct 11 '24 23:10 stale[bot]