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:
(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).