Decimal field returning the incorrect string during saving

Created on 12 August 2019, over 5 years ago
Updated 24 January 2024, 11 months ago

Problem/Motivation

If one enters a value with trailing zeros (eg '123.40') into a decimal field in an entity form then when the value is retrieved from the entity during saving (eg PreSave/Insert/Update hook) will be a float and not a string with the last 0 removed (eg 123.4). But after the entity is saved then re-loaded the value retrieved from the entity is back to having the trailing 0 (eg '123.40').

ie:
Entity Load:
$entity->field_foo->getValue() === [0 => ['value' => '123.40']]
$entity->field_foo->getString() === '123.40'

Entity PreSave/Insert/Update:
$entity->field_foo->getValue() === [0 => ['value' => 123.4]]
$entity->field_foo->getString() === '123.4'

DecimalItem::propertyDefinitions() declares the value property data type as a string where as DecimalItem::preSave() converts it to a float prior to storing in the database.

In most cases this shouldn't be too much of an issue, but this requires extra steps if one were to utilize the value in an entity saving hook as they would need to use something like number_format() and knowledge of the field's scale setting to bring the value up to parity with the how the value is returned everywhere else.

This also causes an issue in the Field Encrypt module β†’ where the returned value is always missing the trailing zeros.

Steps to reproduce

Proposed resolution

Use number_format is preSave.

Remaining tasks

Review
Commit

User interface changes

API changes

Data model changes

Release notes snippet

πŸ› Bug report
Status

Needs work

Version

11.0 πŸ”₯

Component
FieldΒ  β†’

Last updated 1 day ago

Created by

πŸ‡¨πŸ‡¦Canada mdolnik

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Change look good. #15 did the manual testing so just reviewing the code

    Marking as RBTC but I wonder if

    public function providerTestPreSave() { and public function testPreSave($value, $scale, $expected) {

    need to be typehinted even though they're test functions

  • Status changed to Needs work almost 2 years ago
  • πŸ‡¬πŸ‡§United Kingdom alexpott πŸ‡ͺπŸ‡ΊπŸŒ

    One thing that is interesting about this issue is that the schema and property definitions kinda clash.

      /**
       * {@inheritdoc}
       */
      public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
        $properties['value'] = DataDefinition::create('string')
          ->setLabel(new TranslatableMarkup('Decimal value'))
          ->setRequired(TRUE);
    
        return $properties;
      }
    
      /**
       * {@inheritdoc}
       */
      public static function schema(FieldStorageDefinitionInterface $field_definition) {
        return [
          'columns' => [
            'value' => [
              'type' => 'numeric',
              'precision' => $field_definition->getSetting('precision'),
              'scale' => $field_definition->getSetting('scale'),
            ],
          ],
        ];
      }
    

    It really feels like we should have a decimal data type.

    Also this change might result in problems for existing code that assume $this->value is set to float during saving so would require a change record.

  • πŸ‡§πŸ‡ͺBelgium leanderjcc Ghent

    Regarding #22:

    Since 10.2 (see https://www.drupal.org/node/3376447 β†’ ) the decimal data definition is available and used on a DecimalItem.

    Is this issue still relevant?

Production build 0.71.5 2024