Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PUT queries on a Resource with a composite key fail with a duplicate key error #6234

Open
bertrandjamin opened this issue Mar 19, 2024 · 0 comments

Comments

@bertrandjamin
Copy link

bertrandjamin commented Mar 19, 2024

API Platform version(s) affected:
3.2.16

Description
After an update in the latest version of ApiPlatform (from v2.7.x)
Each PUT calls on Resources with composite keys fail with a duplicate error.

It seems that the detection of the existing object fails and so the doctrine flush() try to create the resource rather than updated it.

The limitation seems known (

// TODO: the call to getReference is most likely to fail with complex identifiers
) but I prefer to create an issue so we can follow the resolution.

How to reproduce

  • create a Resource (also Doctrine entity) with a composite Id
  • POST a new resource
  • Set a PUT on this resource
  • The error is triggered

Possible Solution

Awaiting a resolution I have added a specific Processor as workaround

<?php

namespace App\State\Processor;

use ApiPlatform\Metadata\Operation;
use ApiPlatform\Metadata\Put;
use ApiPlatform\State\ProcessorInterface;
use App\Entity\Admin\EntityInterface;
use Doctrine\ORM\EntityManagerInterface;
use Exception;

/**
 * @implements ProcessorInterface<EntityInterface,EntityInterface>
 */
class CompositeIdentifierPutProcessor implements ProcessorInterface
{
    public function __construct(
        private readonly EntityManagerInterface $entityManager,
    ) {
    }

    /**
     * @throws Exception
     */
    public function process(
        mixed $data,
        Operation $operation,
        array $uriVariables = [],
        array $context = []
    ): EntityInterface {

        if (!$operation instanceof Put) {
            throw new Exception('Invalid Operation');
        }

        if (isset($uriVariables['id']['identifiers']) && count($uriVariables['id']['identifiers']) < 2) {
            throw new Exception('This processor should only be used for a Resource with composite identifier');
        }

        $this->entityManager->flush();
        return $data;
    }

}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant