Core: [Question/Potential bug] UniqueEntity validation reloads deserialized entity and discards user data

Created on 10 Oct 2019  路  1Comment  路  Source: api-platform/core

Hi api-platform fans!

This seems like a design issue, not necessarily with api-platform.
Here's the scenario:

  • I have an entity A
  • There's a UniqueEntity constraint validation defined on ManyToOne property B with EAGER fetch mode
  • When I issue a PUT request to change that property with either a null or proper value the WriteListener persists data with wrong value / state

Behind the scenes

  1. ReadListener loads entity and sets it in request.attributes.data https://github.com/api-platform/core/blob/d8e624ba242593365773ec8070d92f548f77d575/src/EventListener/ReadListener.php#L119

  2. DeserializeListener deserializes JSON payload and replaces request.attributes.data item https://github.com/api-platform/core/blob/d8e624ba242593365773ec8070d92f548f77d575/src/EventListener/DeserializeListener.php#L104-L107

  3. Symfony injects request.attributes.data as $data argument in a custom controller

  4. ValidateListener triggers validator on controller result from previous step and invokes UniqueEntityValidator which seems to reload the entity and there fore effectively discards deserialized data from DeserializeListener step https://github.com/symfony/doctrine-bridge/blob/ca6f8537ed349250940a58266630875faec42303/Validator/Constraints/UniqueEntityValidator.php#L138

  5. WriteListener retrieves controller result that references entity that has been reloaded and persists wrong data https://github.com/api-platform/core/blob/d8e624ba242593365773ec8070d92f548f77d575/src/EventListener/WriteListener.php#L76

Result

You are unable to set entity association to null if it has been previously defined and persisted in database.

There's another gotcha, this scenario occurs only when property B in entity A defines EAGER fetch mode. For LAZY and EXTRA_LAZY Doctrine will not reload and rewrite property value.

Simple solution is to not use UniqueEntity validation or EAGER fetch mode. However, I was wondering if there is a good soul to give me an alternative approach. Is there a way to somehow prevent UniqueEntityValidator and Doctrine to fully reload entity state per API request operation?

Tried to pass a cloned entity to validator but that seems to brake down the UniqueEntityValidator
https://github.com/api-platform/core/blob/d8e624ba242593365773ec8070d92f548f77d575/src/Validator/EventListener/ValidateListener.php#L68

question

Most helpful comment

Nice research, thanks for the detailed issue. @teohhanhui do you see an alternative? Maybe that a fix should actually be provided in the UniqueEntityValidator?

>All comments

Nice research, thanks for the detailed issue. @teohhanhui do you see an alternative? Maybe that a fix should actually be provided in the UniqueEntityValidator?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

breitsmiley picture breitsmiley  路  3Comments

tezvi picture tezvi  路  3Comments

silverbackdan picture silverbackdan  路  3Comments

DenisVorobyov picture DenisVorobyov  路  3Comments

rockyweng picture rockyweng  路  3Comments