phpsymfonydoctrineapi-platform.comoptimistic-locking

ApiPlatform/Symfony - Implementing Optimistic Locking on the CRUD API


Symfony, rather Doctrine, offers Optimistic Locking by adding the @Version Annotation to the property of an entity. In practice the version-property on the User-Entity will then look like this:


    /**
     * @Groups({
     *     "user:item:get"
     * })
     * @ORM\Version
     * @ORM\Column(type="integer")
     */
    private $version;

The user:item:get Group in the @Groups-Annotation will add the value of the version-property to the response of a GET-Request. There is no direct implementation of any Request, we use the CRUD-API of an Entity that leverages internal Provider/Persister system.

Let us assume the current version on the User-Resource we are about to change is 10.

Executing a PUT-Request on that Resource with a body like this:

{
  "zip": 10000
  "version": 5
}

will be completely valid. The zip-property will be changed to 10000, even though the version-numbers are mismatched.

What am I doing wrong? Is the internal Persister-system unable to validate the version number by itself or am I providing it incorrectly - is it not supposed to be in the request body?

Thanks!


Solution

  • Okay I upgraded api-platform to version 3.0.0 and now it works as expected...

    If you are using PHP-Attributes as Annotations, the version field should look like this:

        #[
            Groups(["user:item:get","user:item:put"]),
            Version,
            Column(type: Types::INTEGER)
        ]
        private int $version;
    

    Where user:item:get exposes that property on a GET-Request and user:item:put exposes it on a PUT-Request. That way the interal persister-system can validate the version passed in the request-body. So I probably did not have to upgrade, rather I could have just addded the user:item:put Group to the @Groups Annotation.

    Another issue still persists, but that is currently a known problem. Sending the PUT-Request without a version-property in the body does not throw an OptimisticLockException, the request will pass through without error.