Skip to content
Advertisement

When a decimal column is mapped to a typehinted float property, doctrine updates a field even if not changed

I have a User class, with the field

/**
 * @ORMColumn(type="decimal", precision=12, scale=6)
 */
private float $credit = 0;

Or with php8, same behavior:

private int|float $credit = 0;

If I load a user, even without changing anything, at the next flush(), doctrine will send a query to update its credit:

enter image description here

(This is very dangerous because the credit may have been changed in the meanwhile by another script, reverting the change. The credit isn’t supposed to be edited directly from the application, there isn’t even a setCredit() method… )

By adding some dumping in the preUpdate() method, I found the value is changed from:

"-10746.000000" (string)

To:

-10746.000000 (float)

This is not happening if I remove the typehint on the private property:

private $credit = 0; // Working, credit is not updated to db 

Why is this happening? Am I doing something wrong or I should report it as a bug?

Advertisement

Answer

For decimal fields, Doctrine will retrieve the data as a string or null. This is explained on the docs, here.

Since you are defining the property as a float, you force Doctrine to do some type juggling when retrieving the data, which in turn causes the confusing about the entity being ‘dirty’: the value retrieved from the DB is not equal to the value that is stored on the property, e.g. '123.12' !== 123.12.

You should use the type string for decimal properties.

Then you either you cast to float when you want to perform a mathematical operation, or you use something like BC Math if you are interested in precision (which is usually the case when using a decimal type).

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement