Field with type float and orm type decimal is wrongly detected as changed on update #6794

Closed
opened 2026-01-22 15:38:48 +01:00 by admin · 3 comments
Owner

Originally created by @vlud on GitHub (Jul 27, 2021).

Bug Report

Q A
BC Break no
Version 2.9.3

Summary

Fields with declared type float (php 7.4+) and doctrine orm type decimal are detected as changed on PreUpdate event .

Current behavior

My entity has a field of type float, which is declared as such (php 7.4). This same field has a decimal doctrine orm type.

   /**
     * @var float
     *
     * @ORM\Column(type="decimal", scale=2, precision=5)
     */
    private float $discount = 0;

Problem occurs when existing entity gets persisted, but with no new changes. In concrete application, this happens when this entity is relation of some other entity that does get updated. This leads application to think update happened and update event is triggered, with following changeset logged (var_dump($args->getEntityChangeSet()))

array(1) {
  ["discount"]=>
  array(2) {
    [0]=>
    string(1) "0"
    [1]=>
    float(0)
  }
}

How to reproduce

Please checkout following code: https://github.com/vlud/doctrine-orm-float-issue-demo and follow steps defined in ReadMe to reproduce issue.
Note, that issue occurs on entity named BookingWithFloatDecimal, and other entities are behaving as expected.

Expected behavior

PreUpdate should not be triggered when no changes are performed on entity that has field of type float and orm type of decimal. If type is omitted, event is not triggered.

Originally created by @vlud on GitHub (Jul 27, 2021). ### Bug Report | Q | A |------------ | ------ | BC Break | no | Version | 2.9.3 #### Summary Fields with declared type float (php 7.4+) and doctrine orm type decimal are detected as changed on PreUpdate event . #### Current behavior My entity has a field of type **float**, which is declared as such (php 7.4). This same field has a **decimal** doctrine orm type. ``` /** * @var float * * @ORM\Column(type="decimal", scale=2, precision=5) */ private float $discount = 0; ``` Problem occurs when existing entity gets persisted, but with no new changes. In concrete application, this happens when this entity is relation of some other entity that does get updated. This leads application to think update happened and update event is triggered, with following changeset logged (var_dump($args->getEntityChangeSet())) ``` array(1) { ["discount"]=> array(2) { [0]=> string(1) "0" [1]=> float(0) } } ``` #### How to reproduce Please checkout following code: https://github.com/vlud/doctrine-orm-float-issue-demo and follow steps defined in ReadMe to reproduce issue. Note, that issue occurs on entity named `BookingWithFloatDecimal`, and other entities are behaving as expected. #### Expected behavior PreUpdate should not be triggered when no changes are performed on entity that has field of type float and orm type of decimal. If type is omitted, event is not triggered.
admin closed this issue 2026-01-22 15:38:48 +01:00
Author
Owner

@mbabker commented on GitHub (Jul 27, 2021):

This has to do with how the two decimal field types (decimal and float) in the DBAL are handled (see https://www.doctrine-project.org/projects/doctrine-dbal/en/2.13/reference/types.html#decimal-types) and how the UoW detects changes.

The best way to deal with this when using a decimal type is to store the decimal value as a string in your entity class property (since that will match up with how DecimalType handles conversions in the DBAL) and have your getter and setter handle type conversions so your application is working with floats but the ORM is tracking strings. Something like this would do the trick:

/**
 * @ORM\Entity
 * @ORM\Table(name="booking_float_decimal")
 */
class BookingWithFloatDecimal
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue
     */
    private $id;

    /**
     * @ORM\Column(type="decimal", scale=2, precision=5)
     */
    private string $discount = '0.00000';

    /**
     * @return mixed
     */
    public function getId()
    {
        return $this->id;
    }

    public function getDiscount(): float
    {
        return (float) $this->discount;
    }

    public function setDiscount(float $discount): void
    {
        $this->discount = sprintf('%.5f', $discount);
    }
}
@mbabker commented on GitHub (Jul 27, 2021): This has to do with how the two decimal field types (decimal and float) in the DBAL are handled (see https://www.doctrine-project.org/projects/doctrine-dbal/en/2.13/reference/types.html#decimal-types) and how the UoW detects changes. The best way to deal with this when using a decimal type is to store the decimal value as a string in your entity class property (since that will match up with how `DecimalType` handles conversions in the DBAL) and have your getter and setter handle type conversions so your application is working with floats but the ORM is tracking strings. Something like this would do the trick: ```php /** * @ORM\Entity * @ORM\Table(name="booking_float_decimal") */ class BookingWithFloatDecimal { /** * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue */ private $id; /** * @ORM\Column(type="decimal", scale=2, precision=5) */ private string $discount = '0.00000'; /** * @return mixed */ public function getId() { return $this->id; } public function getDiscount(): float { return (float) $this->discount; } public function setDiscount(float $discount): void { $this->discount = sprintf('%.5f', $discount); } } ```
Author
Owner

@vlud commented on GitHub (Jul 28, 2021):

Thank you for the advice, @mbabker :) We ended up using different workaround - simply not defining this particular field as float. It works in our particular case.

@vlud commented on GitHub (Jul 28, 2021): Thank you for the advice, @mbabker :) We ended up using different workaround - simply not defining this particular field as float. It works in our particular case.
Author
Owner

@beberlei commented on GitHub (Aug 4, 2021):

Closing as its not a bug, but just related to the float/decimal specifics in PHP vs DBAL vs DBs

@beberlei commented on GitHub (Aug 4, 2021): Closing as its not a bug, but just related to the float/decimal specifics in PHP vs DBAL vs DBs
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#6794